/****************************************************
 * File: mtp.c
 *
 * Author: Fred Engler
 *
 * Description: Contains the user interface for finding
 * overlapping pairs and picking MTP clones, and stepping
 * through them, etc.  Also contains the code for finding
 * fingerprint-based overlapping pairs.
 ****************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "clam.h"
#include "mtp.h"
//#include "draft.h"
#include <glib.h>
//#include "glib_port.h"

static int CANDIDATE=1000;

#define Show { if(graphActivate(gMTP)){graphPop(); graphRedraw();} else if(graphActivate(gStep)){graphPop(); graphRedraw();} }

struct pairlist *pairs = NULL;   /* Two dimensional dynamically
                                  * allocated array with expandable
                                  * rows for holding all pairs for all
                                  * contigs, with one row per contig*/
int *pair_cnt = NULL;            /* Dynamically allocated array for
                                  * storing the number of pairs in the
                                  * contig (index of array == ctg #) */
int cur_pair=-1;                 /* The pair being stepped through.*/

struct picklist *picks = NULL;   /* Two dimensional dynamically
                                  * allocated array with expandable
                                  * rows for holding all MTP clones
                                  * for all contigs, with one row per
                                  * contig*/
int *pick_cnt = NULL;            /* Dynamically allocated array for
                                  * storing the number of MTP clones
                                  * in the contig (index of array ==
                                  * ctg #) */
int cur_pick=-1;                 /* The MTP clone being stepped through.*/

int *max_pairs=NULL;             /* For memory management*/
int *max_picks=NULL;             /* For memory management*/

int pick_pair_start=FALSE;       /* For picking the starting clone for pairs*/

extern GtkWidget *ctg_window;
extern int min_size_pen, max_size_pen, min_olap_pen, max_olap_pen;
extern int gEvaluateClone;
extern void updateproj();

extern void show_help();
extern char *rindex();
extern int filCheck();
extern int graphQueryOpen();
extern int Zbcm();
extern void refresh_all_track_colors();
extern void refresh_gtk_ctgdisplay();
extern void gtk_ctgdisplay();
extern void displayFPmtp();
extern int compute_pairs();
extern int GetSize();
extern void pick_exp_and_mtp();
extern BOOL unbury();
extern void ZselectMTP();
extern int loadCz(struct tmpCz *Cx, int cin);
extern int loadSizeCz(struct tmpCz *Cx, int cin);
static void show_mtp_help();
extern int get_ctg_id(int ctg);
extern int get_clone_id(int ctgID, char *c);
void get_mandatory(int ctgID, GPtrArray *mandatory);


static void ZstepWindow();
void quitMTP(), quitStep(), quitAdvanced();
static void pickg(), hitCR(), hitCR2(), pickg2(), hitCR3();
void ZadvancedBSS();
void quitAdvancedBSS();
void ZmandatoryClones(void);
void pairsParameters(), mtpParameters();

int gMTP;
static int gStep, gAdvancedBSS, gMandatoryClones;
static int contigBox, minOlapBox, maxOlapBox, minSharedBox,
  bssFileBox, pairsBox, picksBox, minScoreBox, minIdBox,
  maxSeqOlapBox, multCtgRatioBox, selCtgBox, pairsFileBox, pickStartBox,
  messageBox, messageBox2,  weightBox, endBox;
static int fpArc, size1Arc, size2Arc, bssArc, showFpArc, onlyPosArc, onlySingleArc, allCtgArc, singleCtgArc, largeClnArc;
static int noneArc, tileArc, sentArc, readyArc, shotgunArc, finishedArc, sdArc;

/* cari 3 feb 05 - chg 10 to 14 because that is what he is reading */
static char contigText[14], minOlapText[14], maxOlapText[14],
            minSharedText[14], maxSharedText[14], uniqueSharedText[14],
            fpText[14], fp2Text[14], minScoreText[14], minIdText[14],
            maxSeqOlapText[14], multCtgRatioText[14], selCtgText[14],
            weightText[14], mandnumText[30];
int use_fp_pairs=TRUE, use_bss_pairs=FALSE;
static int have_pairs=FALSE, have_picks=FALSE;
static int show_fp=TRUE;

char mtp_output_file[MAXPATHLEN] = "";
char pair_output_file[MAXPATHLEN] = "";
char bssFileText[MAXPATHLEN+1]="";    

char pairsFileText[MAXPATHLEN+1]="";  /* Path to pairs file when
                                       * loading*/
char messageText[50]="";              /* Stats overview displayed in
                                       * window (summary of stdout)*/
char messageText2[50]="";             /* Stats overview displayed in
                                       * window (summary of stdout)*/
int Use_sizes=0;

static int LR_overlap;    /* CAS overlap between MTP pair shared bands
                           * - either sizes for avgbandsize*/
static int ctg=-1;          /* contig to analyze */
int minOlap=-5;     /* minimum overlap of two potential MTPs */
int maxOlap= 20;    /* maximum overlap between two potential MTPs */
static int minShared= 3;   /* minimum shared bands between two
                            * potential MTPs */
int maxShared= 10;         /* maximum shared bands between two
                            * potential MTPs */
static int uniqueShared=3; /* minimum bands shared uniquely with
                              spanner and left clone (or spanner and
                              right clone)*/



static int max_span_mis = 2;     /* number of false negatives for spanner*/
static int max_flank_mis = 3;    /* number of false negatives for flankers*/
int run_on_single_ctg=FALSE;     /* If true, only find pairs for selected_ctg*/
int selected_ctg=1;              /* The contig to run pairs on if
                                  * run_on_single_ctg is true*/
int minScore = 400;        /* minimum BLAST score to accept hit*/
int minId = 97;            /* minimum BLAST %id to accept hit*/

int max_seq_olap=50000;    /* Maximum bes-based sequence overlap (or gap)*/
int only_pos_olap=FALSE;   /* If true, only consider positive
                            * bes-based overlaps*/
int only_single_bes=0;  /* if true, discard all hits where multiple
                            * seqCtgs hit the same BES*/
int mult_ctg_ratio=0;      /* Minimum ratio of highest hitting contig
                            * hits to other contig hits*/
int prefer_large=TRUE;     /* If true, weight pair edges heavier if
                            * clones are small*/
gint shared_weight = 1, unacc_weight = 2, spanmis_weight = 10;
int mand_num = 5;

extern int MaxCtgClones;
extern int *clonekey[MAXCTGS];
extern int num_clones[MAXCTGS];

extern int ctgkey[MAXCTGS][3];
extern int num_ctgs;
extern char endText[14]; 
extern int g9a, g92; 

typedef struct
{
    gchar* name;
    GtkWidget* selector;
    enum {OK, CANCEL} button;
} FileSelectionData;


#define NONE_MASK     ((guchar)1 << 0)
#define TILE_MASK     ((guchar)1 << 1)
#define SENT_MASK     ((guchar)1 << 2)
#define READY_MASK    ((guchar)1 << 3)
#define SHOTGUN_MASK  ((guchar)1 << 4)
#define FINISHED_MASK ((guchar)1 << 5)
#define SD_MASK       ((guchar)1 << 6)
#define SEQSTAT_MASK  (((guchar)1 << 7) - 1)
static guchar mandatory_seqstats = NONE_MASK;

static struct {
    const gchar *name;
    const gchar *format;
    void *value;
} mtp_config[] = {{"Mndtry", "%c", &mandatory_seqstats},
                  {"MinOlap", "%d", &minOlap},
                  {"MaxOlap", "%d", &maxOlap},
                  {"MinShared", "%u", &minShared},
//                  {"Weight", "%u", &spanmis_weight},
                  {"MinScore", "%u", &minScore},
                  {"Identity", "%u", &minId},
                  {"MaxSeqOlap", "%d", &max_seq_olap},
                  {"CtgRatio", "%u", &mult_ctg_ratio}};

/*                     DEF: sortPairs
 * Sort a pair array based on left clone's left end value*/
static int sortPairs(struct pair *p1, struct pair *p2){
  if(p1->x1 < p2->x1) return -1;
  if(p1->x1 > p2->x1) return 1;
  return 0;
}


void
file_selection_cb(GtkButton* button, FileSelectionData* sdata)
{
    if (sdata->button == OK) {
        sdata->name = g_strdup(gtk_file_selection_get_filename(
                                   GTK_FILE_SELECTION(sdata->selector)));
    }
    gtk_widget_destroy(GTK_WIDGET(sdata->selector));
    gtk_main_quit();
}


static void
pickg3(int box,double x,double y)
{
/* can not split define over two lines - sun does not like it */
#define TOGGLE_BIT(mask, bitfield) (((bitfield) & (mask)) ? ((bitfield) & ~(mask)) : ((bitfield) | (mask)))

    if (box == noneArc) {
        mandatory_seqstats = TOGGLE_BIT(NONE_MASK, mandatory_seqstats);
    }
    else if (box == tileArc) {
        mandatory_seqstats = TOGGLE_BIT(TILE_MASK, mandatory_seqstats);
    }
    else if(box == sentArc) {
        mandatory_seqstats = TOGGLE_BIT(SENT_MASK, mandatory_seqstats);
    }
    else if(box == readyArc) {
        mandatory_seqstats = TOGGLE_BIT(READY_MASK, mandatory_seqstats);
    }
    else if(box == shotgunArc) {
        mandatory_seqstats = TOGGLE_BIT(SHOTGUN_MASK, mandatory_seqstats);
    }
    else if(box == finishedArc) {
        mandatory_seqstats = TOGGLE_BIT(FINISHED_MASK, mandatory_seqstats);
    }
    else if(box == sdArc) {
        mandatory_seqstats = TOGGLE_BIT(SD_MASK, mandatory_seqstats);
    }
    ZmandatoryClones();
#undef TOGGLE_BIT
}
void
mtp_update_fp_class_pars(void)
{
    switch (Pz.fp_class) {
    case AGAROSE:
        minOlap = 0;
        maxOlap = 20;
        minShared = 6;
        uniqueShared = 6;
        break;
    case HICF:
        minOlap = 6;
        maxOlap = 50;
        minShared = 14;
        uniqueShared = 8;
        break;
    default:
        g_assert_not_reached();
        break;
    }
}
static void
read_config_par(const gchar *config, const gchar *name, const gchar *format,
                void *value)
{
    int ret;

    g_return_if_fail(config != NULL);

    if (strcmp(format, "%c") == 0) {
        guint buf;
        ret = sscanf(config + strlen(name), "%u", &buf);
        *((guchar *)value) = (guchar)buf;
        if (ret != 1) {
            g_warning("Failed to read '%s' configuration parameter value:"
                      "\n\twill use default value (%u)",
                      name, *((guchar *)value));
        }
    }
    else if (strcmp(format, "%u") == 0) {
        ret = sscanf(config + strlen(name), format, (guint *)value);
        if (ret != 1) {
            g_warning("Failed to read '%s' configuration parameter value:"
                      "\n\twill use default value (%u)",
                      name, *((guint *)value));
        }
    }
    else if (strcmp(format, "%d") == 0) {
        ret = sscanf(config + strlen(name), format, (gint *)value);
        if (ret != 1) {
            g_warning("Failed to read '%s' configuration parameter value:"
                      "\n\twill use default value (%d)",
                      name, *((gint *)value));
        }
    }
    else {
        g_assert_not_reached();
    }
}

static void
write_config_par(FILE *stream, const gchar *name, const gchar *format,
                 const void *value)
{
    fprintf(stream, " %s ", name);
    if (strcmp(format, "%c") == 0) {
        fprintf(stream, "%u", *((const guchar *)value));
    }
    else if (strcmp(format, "%u") == 0) {
        fprintf(stream, format, *((const guint *)value));
    }
    else if (strcmp(format, "%d") == 0) {
        fprintf(stream, format, *((const gint *)value));
    }
    else {
        g_assert_not_reached();
    }
}

void
mtp_load_configuration(const gchar *config)
{
    const gchar *ch_p;
    guint i;

    for (i = 0; i < G_N_ELEMENTS(mtp_config); ++i) {
        ch_p = strstr(config, mtp_config[i].name);
        if (ch_p != NULL) {
            read_config_par(ch_p, mtp_config[i].name, mtp_config[i].format,
                            mtp_config[i].value);
        }
    }

    ch_p = strstr(config, "PosOnly");
    if (ch_p != NULL) {
        only_pos_olap = TRUE;
    }

    ch_p = strstr(config, "MultBES");
    if (ch_p != NULL) {
        only_single_bes = FALSE;
    }
}

void
mtp_save_configuration(FILE *stream)
{
    guint i;

    fputs("// MTP", stream);
    for (i = 0; i < G_N_ELEMENTS(mtp_config); ++i) {
        write_config_par(stream, mtp_config[i].name, mtp_config[i].format,
                         mtp_config[i].value);
    }
    if (only_pos_olap) {
        fputs(" PosOnly", stream);
    }
    if (!only_single_bes) {
        fputs(" MultBES", stream);
    }
    fputs("\n", stream);
}


/*                     DEF: get_pairs_mem
 * Get memory for, or expand if needed, a pair array*/
/* WMN 10/10/06 altered this to start @ 10 and grow exponentially
    It was starting at 1000 and using too much memory */
static void
get_pairs_mem(struct pair **p, int numpairs, int *maxpairs){
  if(numpairs >= *maxpairs-1){
    if(*maxpairs==0){
      *maxpairs=10;
      *p=calloc(*maxpairs,sizeof(struct pair));
      NOMEM2(*p,"pairs");
    }
    else if (*maxpairs <= 1024){
      *maxpairs *= 2;
      *p=realloc(*p,sizeof(struct pair)*(*maxpairs));
      NOMEM2(*p,"pairs");
    }
    else {
      *maxpairs += 1000;
      *p=realloc(*p,sizeof(struct pair)*(*maxpairs));
      NOMEM2(*p,"pairs");
    }
  }
}

/*                     DEF: get_picks_mem
 * Get memory for, or expand if needed, a pick array*/
static void
get_picks_mem(struct pick **p, int numpicks, int *maxpicks){
  if(numpicks >= *maxpicks-1){
    if(*maxpicks==0){
      *maxpicks=500;
      *p=calloc(*maxpicks,sizeof(struct pick));
      NOMEM2(*p,"picks");
    }
    else{
      *maxpicks+=500;
      *p=realloc(*p,sizeof(struct pick)*(*maxpicks));
      NOMEM2(*p,"picks");
    }
  }
}

/*                     DEF: free_pairs_mem
 * Frees all memory associated with the current pairs set*/
static void
free_pairs_mem(){
  int i;

  if (pairs != NULL) { /* martin 14 feb 05 */
    for(i=1;i<=max_contig;i++){
      if(pairs[i].p!=NULL) g_free(pairs[i].p);
    }
  }
  g_free(pairs);
  pairs=NULL;
  g_free(pair_cnt);
  pair_cnt=NULL;
  g_free(max_pairs);
  max_pairs=NULL;
}

/*                     DEF: free_picks_mem
 * Frees all memory associated with the current picks set*/
static void
free_picks_mem(){
  int i;

  if (picks != NULL) { /* martin 14 feb 05 */
    for(i=1;i<=max_contig;i++){
      g_free(picks[i].p);
      picks[i].p = 0;
    }
  }
  g_free(picks);
  picks=NULL;
  g_free(pick_cnt);
  pick_cnt=NULL;
  g_free(max_picks);
  max_picks=NULL;
}

/*                     DEF: confirm_overwrite
 * Query user before clearing old pairs if the overlapping
 * pairs has already been run.*/
static int
confirm_overwrite(){
  if(have_pairs){
    if(messQuery("Remove all old pairs?\n")){
      free_pairs_mem();
    }
    else{
      graphBoxDraw(pairsBox, BLACK, LIGHTGRAY);
      return 0;
    }
    if(have_picks){
      free_picks_mem();
    }
  }
  return 1;
}

/*                     DEF: add_to_pairs
 * Add a good pair to the 'pairs' structure.*/
void
add_to_pairs(int ctg, enum pairTypes pair_type,
             char *c1, char *c2, char* draft_clone,char *cspan, char *clflank, char *crflank,
             int x1, int y1, int x2, int y2,
             int index1, int index2, int indexspan,
             int indexlflank, int indexrflank,
             int olap, int score, int c1size, int c2size,
             int c1size_from_file, int c2size_from_file,
             struct pair_bin *bin_values){
  int i;

  if(pairs==NULL){
    pairs = g_malloc(sizeof(struct pairlist) * (max_contig+1));
    memset(pairs,0,sizeof(struct pairlist) * (max_contig+1));
    for(i=0; i<=max_contig; i++) pairs[i].p=NULL;
  }
  if(pair_cnt==NULL){
    pair_cnt = g_malloc(sizeof(int) * (max_contig+1));
    for(i=0; i<=max_contig; i++) pair_cnt[i]=0;
  }
  if(max_pairs==NULL){
    max_pairs = g_malloc(sizeof(int) * (max_contig+1));
    for(i=0; i<=max_contig; i++) max_pairs[i]=0;
  }

  if(pair_cnt[ctg]>=max_pairs[ctg])
    get_pairs_mem(&(pairs[ctg].p), pair_cnt[ctg], &(max_pairs[ctg]));

  memset(&pairs[ctg].p[pair_cnt[ctg]],0,sizeof(struct pair));
  strcpy(pairs[ctg].p[pair_cnt[ctg]].c1,c1);
  strcpy(pairs[ctg].p[pair_cnt[ctg]].c2,c2);
  pairs[ctg].p[pair_cnt[ctg]].x1=x1;
  pairs[ctg].p[pair_cnt[ctg]].y1=y1;
  pairs[ctg].p[pair_cnt[ctg]].x2=x2;
  pairs[ctg].p[pair_cnt[ctg]].y2=y2;
  pairs[ctg].p[pair_cnt[ctg]].index1=index1;
  pairs[ctg].p[pair_cnt[ctg]].index2=index2;
  pairs[ctg].p[pair_cnt[ctg]].olap=olap;
  pairs[ctg].p[pair_cnt[ctg]].weight_score=score;
  pairs[ctg].p[pair_cnt[ctg]].pair_type=pair_type;
  pairs[ctg].p[pair_cnt[ctg]].c1size=c1size;
  pairs[ctg].p[pair_cnt[ctg]].c2size=c2size;
  pairs[ctg].p[pair_cnt[ctg]].c1size_from_file=c1size_from_file;
  pairs[ctg].p[pair_cnt[ctg]].c2size_from_file=c2size_from_file;
  if(pair_type==FINGERPRINT){
    strcpy(pairs[ctg].p[pair_cnt[ctg]].cspan,cspan);
    if(clflank!=NULL) strcpy(pairs[ctg].p[pair_cnt[ctg]].clflank,clflank);
    if(crflank!=NULL) strcpy(pairs[ctg].p[pair_cnt[ctg]].crflank,crflank);
    pairs[ctg].p[pair_cnt[ctg]].indexspan=indexspan;
    pairs[ctg].p[pair_cnt[ctg]].indexlflank=indexlflank;
    pairs[ctg].p[pair_cnt[ctg]].indexrflank=indexrflank;
    if(bin_values!=NULL) pairs[ctg].p[pair_cnt[ctg]].bin_values = *bin_values;
  }
  if(pair_type == BSS_DRAFT) {
    strcpy(pairs[ctg].p[pair_cnt[ctg]].clflank, clflank);
    strcpy(pairs[ctg].p[pair_cnt[ctg]].crflank, crflank);
    strcpy(pairs[ctg].p[pair_cnt[ctg]].draft_clone, draft_clone);
    pairs[ctg].p[pair_cnt[ctg]].indexspan = indexspan;
  }

  pair_cnt[ctg]++;
}

/*                     DEF: add_to_picks
 * Add a picked MTP pair to the 'picks' structure.*/
void
add_to_picks(int ctg, struct pair *picked, int exp_pos1,
             int exp_pos2, int exp_cnt, int ljunction, int rjunction){
  int i;

  if(picks==NULL){
    picks = g_malloc(sizeof(struct picklist) * (max_contig+1));
    for(i=0; i<=max_contig; i++) picks[i].p=NULL;
  }
  if(pick_cnt==NULL){
    pick_cnt = g_malloc(sizeof(int) * (max_contig+1));
    for(i=0; i<=max_contig; i++) pick_cnt[i]=0;
  }
  if(max_picks==NULL){
    max_picks = g_malloc(sizeof(int) * (max_contig+1));
    for(i=0; i<=max_contig; i++) max_picks[i]=0;
  }

  if(pick_cnt[ctg]>=max_picks[ctg])
    get_picks_mem(&(picks[ctg].p), pick_cnt[ctg], &(max_picks[ctg]));

  picks[ctg].p[pick_cnt[ctg]].picked=picked;
  picks[ctg].p[pick_cnt[ctg]].exp_pos1=exp_pos1;
  picks[ctg].p[pick_cnt[ctg]].exp_pos2=exp_pos2;
  picks[ctg].p[pick_cnt[ctg]].exp_cnt=exp_cnt;
  picks[ctg].p[pick_cnt[ctg]].ljunction=ljunction;
  picks[ctg].p[pick_cnt[ctg]].rjunction=rjunction;

  pick_cnt[ctg]++;
}

/*                     DEF: find_pair
 * Returns a pointer to the pair containing clones c1 and c2.
 * There should not be more than one */
struct pair *
find_pair(int ctg, char *c1, char *c2)
{
    int i;
    struct pair *p = NULL;

    if (pair_cnt != NULL) { /* martin 14 feb 05 */
        for (i = 0; i < pair_cnt[ctg]; i++) {
            if (!strcmp(pairs[ctg].p[i].c1, c1)) {
                if (!strcmp(pairs[ctg].p[i].c2, c2)) {
                    if (p == NULL)
                        p = &(pairs[ctg].p[i]);
                    else  {
//                        printf("WARNING:  Duplicate pair (%s, %s) in ctg%d\n",
//                               c1, c2, ctg);
                    }

                }
            }
        }
    }
    return p;
}



/*                     DEF: check_fp_integrity
 * There are two ways this function may be called: with flankers, or
 * without flankers. If the flankers are -1 (the initial step in
 * finding a good pair), the spanner's bands are compared to the pair
 * candidate's pairs. If the flankers are not -1 (we have a potential
 * spanner and now must find good flankers), we try to confirm with
 * the flankers all bands not confirmed by the spanner. A failure code
 * is returned giving the status of the current candidate. */
static int check_fp_integrity(int index1, int index2,
                              int indexspan, int indexlflank, int indexrflank,
                              struct pair_bin *bin_values){
  int i, j, start;
  struct tmpCz Cspanz, Cflz, Cfrz;
  enum matchtypes {NONE, L, R, LR, FLANK} *lmatch, *rmatch, *spanmatch, *flmatch=NULL, *frmatch=NULL;
  int diff;
  int span_mis=0, flank_L_mis=0, flank_R_mis=0,
    span_L_share=0, span_LR_share=0, span_R_share=0,
    flank_L_share=0, flank_R_share=0;
  int failures=0;

  loadCzfast(&C1z,index1);
  loadCzfast(&C2z,index2);
  loadCzfast(&Cspanz,indexspan);
  if(indexlflank!=-1) loadCzfast(&Cflz,indexlflank);
  if(indexrflank!=-1) loadCzfast(&Cfrz,indexrflank);

  lmatch = (enum matchtypes *) g_malloc(sizeof(enum matchtypes) * C1z.nbands);
  rmatch = (enum matchtypes *) g_malloc(sizeof(enum matchtypes) * C2z.nbands);
  spanmatch = (enum matchtypes *) g_malloc(sizeof(enum matchtypes) * Cspanz.nbands);
  if(indexlflank!=-1)
      flmatch = (enum matchtypes *) g_malloc(sizeof(enum matchtypes) * Cflz.nbands);
  if(indexrflank!=-1)
      frmatch = (enum matchtypes *) g_malloc(sizeof(enum matchtypes) * Cfrz.nbands);

  for(i=0;i<C1z.nbands;i++) lmatch[i]=NONE;
  for(i=0;i<C2z.nbands;i++) rmatch[i]=NONE;
  for(i=0;i<Cspanz.nbands;i++) spanmatch[i]=NONE;
  if(indexlflank!=-1) for(i=0;i<Cflz.nbands;i++) flmatch[i]=NONE;
  if(indexrflank!=-1) for(i=0;i<Cfrz.nbands;i++) frmatch[i]=NONE;

  /* Find matches between spanner and left clone*/
  start=0;
  for(i=0;i<Cspanz.nbands;i++){
    for(j=start;j<C1z.nbands;j++){
      if(lmatch[j]==NONE){  /*Don't assign the same spanner band to
                             * two left bands*/
        diff=Cspanz.coords[i] - C1z.coords[j];
        if(Ztol(Cspanz.coords[i],diff)){
          spanmatch[i]=L;
          lmatch[j]=L;
          start=j+1;
          break;
        }
        else if(diff<0){
          start=j;
          break;
        }
      }
    }
  }

  /* Find matches between spanner and right clone*/
  start=0;
  for(i=0;i<Cspanz.nbands;i++){
    for(j=start;j<C2z.nbands;j++){
      if(rmatch[j]==NONE){  /*Don't assign the same spanner band to
                             * two right bands*/
        diff=Cspanz.coords[i] - C2z.coords[j];
        if(Ztol(Cspanz.coords[i],diff)){
          if(spanmatch[i]==L) spanmatch[i]=LR;
          else spanmatch[i]=R;
          rmatch[j]=R;
          start=j+1;
          break;
        }
        else if(diff<0){
          start=j;
          break;
        }
      }
    }
  }

  if(indexlflank!=-1){
    start=0;
    /* Make sure left clones' unique bands are accounted for by the
     * left flanker*/
    for(i=0;i<C1z.nbands;i++){
      if(lmatch[i]==NONE){
        for(j=start;j<Cflz.nbands;j++){
          if(flmatch[j]==NONE){  /*Don't assign the same flanker band
                                  * to two left bands*/
            diff=C1z.coords[i] - Cflz.coords[j];
            if(Ztol(C1z.coords[i],diff)){
              lmatch[i]=FLANK;
              flmatch[j]=FLANK;
              start=j+1;
              break;
            }
            else if(diff<0){
              start=j;
              break;
            }
          }
        }
      }
    }
  }

  if(indexrflank!=-1){
    start=0;
    /* Make sure right clones' unique bands are accounted for by the
     * right flanker*/
    for(i=0;i<C2z.nbands;i++){
      if(rmatch[i]==NONE){
        for(j=start;j<Cfrz.nbands;j++){
          if(frmatch[j]==NONE){  /*Don't assign the same flanker band
                                  * to two right bands*/
            diff=C2z.coords[i] - Cfrz.coords[j];
            if(Ztol(C2z.coords[i],diff)){
              rmatch[i]=FLANK;
              frmatch[j]=FLANK;
              start=j+1;
              break;
            }
            else if(diff<0){
              start=j;
              break;
            }
          }
        }
      }
    }
  }

  /*Add up bands*/
  for(i=0;i<Cspanz.nbands; i++){
    if(spanmatch[i]==NONE) span_mis++;
    else if(spanmatch[i]==L) span_L_share++;
    else if(spanmatch[i]==LR) span_LR_share++;
    else if(spanmatch[i]==R) span_R_share++;
  }
  for(i=0;i<C1z.nbands; i++){
    if(lmatch[i]==NONE) flank_L_mis++;
    else if(lmatch[i]==FLANK) flank_L_share++;
  }
  for(i=0;i<C2z.nbands; i++){
    if(rmatch[i]==NONE) flank_R_mis++;
    else if(rmatch[i]==FLANK) flank_R_share++;
  }
/* CAS - read in sizes to Cspanz and use them instead of just shared x averagebandsz */
  if (Pz.useSz) {
      if (loadSizeCz(&Cspanz, indexspan) ) {
          LR_overlap=0;
          /* bands and sizes are in descending order, but the largest size goes
             with the smallest migration rate */
          for(j=Cspanz.nbands-1, i=0;i<Cspanz.nbands; i++, j--){
              if (spanmatch[i]==LR) LR_overlap+=Cspanz.coords[j];
          }
      }
      else {
          LR_overlap = span_LR_share * Proj.avgbandsize;
      }
  }

  bin_values->span_L_share=span_L_share;
  bin_values->span_LR_share=span_LR_share;
  bin_values->span_R_share=span_R_share;
  bin_values->flank_L_share=flank_L_share;
  bin_values->flank_R_share=flank_R_share;
  bin_values->span_mis=span_mis;
  bin_values->flank_L_mis=flank_L_mis;
  bin_values->flank_R_mis=flank_R_mis;

  /* Set bits in failures*/
/*   if(span_LR_share>maxShared) */
/*     failures |= MAX_BAND_MASK; */
  if(span_LR_share<minShared)
    failures |= MIN_BAND_MASK;
  if((span_L_share < uniqueShared) || (span_R_share<uniqueShared))
    failures |= SPAN_FAILURE_MASK;
  if((indexlflank== -1) || (flank_L_mis>0))
    failures |= HAVE_LFLANK_MISMATCH_MASK;
  if((indexrflank== -1) || (flank_R_mis>0))
    failures |= HAVE_RFLANK_MISMATCH_MASK;

  free(lmatch);
  lmatch = 0;
  free(rmatch);
  rmatch = 0;
  free(spanmatch);
  spanmatch = 0;
  if(indexlflank!= -1) free(flmatch);
  if(indexrflank!= -1) free(frmatch);

  return failures;
}

static int check_fp_shared(int index1, int index2) {
  int i, j, start, num=0;
  enum types {NONE, M} *match1, *match2;
  int diff;

  loadCzfast(&C1z,index1);
  loadCzfast(&C2z,index2);

  match1 = (enum types *) g_malloc(sizeof(enum types) * C1z.nbands);
  match2 = (enum types *) g_malloc(sizeof(enum types) * C2z.nbands);

  match1 = (enum types *) g_malloc(sizeof(enum types) * C1z.nbands);
  match2 = (enum types *) g_malloc(sizeof(enum types) * C2z.nbands);

  for(i=0;i<C1z.nbands;i++) match1[i]=NONE;
  for(i=0;i<C2z.nbands;i++) match2[i]=NONE;

  start=0;
  for(i=0;i<C1z.nbands;i++){
    for(j=start;j<C2z.nbands;j++){
      if(match2[j]==NONE){  
        diff=C1z.coords[i] - C2z.coords[j];
        if(Ztol(C1z.coords[i],diff)){
          match1[i]=M;
          match2[j]=M;
          start=j+1;
          break;
        }
        else if(diff<0){
          start=j;
          break;
        }
      }
    }
  }

  for(i=0;i<C1z.nbands; i++)
    if(match1[i]==M) num++;

  free(match1);
  match1 = 0;
  free(match2);
  match2 = 0;
  return num;
}

/*                     DEF: get_span_candidates
 * Fill candidates array with all clones between the start clone and
 * end clone*/
static int
get_span_candidates(struct contig *start, struct contig *end,
                    int pair_midpt, struct spanner *candidates){
  int num=0;
  struct contig *cptr;
  CLONE *clp, *clpstart, *clpend;

  clpstart=arrp(acedata, start->next, CLONE);
  clpend=arrp(acedata, end->next, CLONE);
  for(cptr=start->new; cptr!=end; cptr=cptr->new){
    if(num>=CANDIDATE) {
      printf("WARNING:  More than %d spanners!!\n", CANDIDATE);
      break;
    }
    clp=arrp(acedata, cptr->next, CLONE);
    if((clp->x < MIN(clpstart->y, clpend->x)) &&
       (clp->y > MAX(clpstart->y, clpend->x))){
      candidates[num].cptrspan=cptr;
      candidates[num++].dist = abs((clp->y - clp->x)/2 - pair_midpt);
    }
  }
  return num;
}

/*                     DEF: sortSpanners
 * Sort based on distance from pair midpt*/
static int
sortSpanners(const struct spanner *p1, const struct spanner *p2){
  if(p1->dist > p2->dist) return 1;
  if(p1->dist < p2->dist) return -1;
  return 0;
}

/*Jingmei Sep. 05
*			DEF: sortctgRight
* Sort contig based on its clones' right end */
static int
sortctgRight(const void *orig_a, const void *orig_b)
{
  int y1, y2;

  struct contig *a;
  struct contig *b;

  a = (struct contig *)orig_a;
  b = (struct contig *)orig_b;

  y1 = arr(acedata, a->next, CLONE).y;
  y2 = arr(acedata, b->next, CLONE).y;

  if(y1 < y2) return -1;
  if(y1 > y2) return 1;
  return 0;
}

/*Jingmei Sep. 05
*		       DEF: orderclonesRight
* order clones based on their right end*/
static void
orderclonesRight(int ctg, struct contig *root_right)
{
  int i, count;

  count = contigs[ctg].count;
  if(count <= 1) return;

  qsort(root_right, count, sizeof(struct contig), sortctgRight);
  for(i = 0; i < count-1; i++)
    root_right[i].new = &(root_right[i+1]);
  root_right[i].new = NULL;
}

/*Jingmei Sep. 05
*		      DEF: get_leftflank_candidates
* get the left flanker candidates */
static void
get_leftflank_candidates(struct contig *root_right, struct contig *cptr1,
                         struct contig *cptr2, int y_min, int y_max,
                         struct contig **first, struct contig **last)
{
  struct contig *cptr;
  CLONE *clone;

  for(cptr = root_right; cptr!=NULL; cptr=cptr->new) {
    if(cptr == cptr1) continue;
    if(cptr == cptr2) continue;
    clone = arrp(acedata, cptr->next, CLONE);
    if(clone->y < y_min) {
      continue;
    } else if(clone->y <= y_max) {
        if(*first == NULL)
          *first = cptr;
    } else {
        *last = cptr;
        break;
    }
  }
}

/*Jingmei Sep. 05
*		      DEF: get_rightflank_candidates
* get the right flanker candidates */
static void get_rightflank_candidates(struct contig *cptr1, struct contig *cptr2, int x_min, int x_max, struct contig **first, struct contig **last) {
  struct contig *cptr;
  CLONE *clone;

  for(cptr = root; cptr!=NULL; cptr=cptr->new) {
    if(cptr == cptr1) continue;
    if(cptr == cptr2) continue;
    clone = arrp(acedata, cptr->next, CLONE);
    if(clone->x < x_min) {
      continue;
    } else if (clone->x <= x_max) {
      if(*first == NULL)
        *first = cptr;
    } else {
      *last = cptr;
      break;
    }
  }
}

int use_mandatory(CLONE* clp)
{
    if ( (clp->seqstat == TILE && (mandatory_seqstats & TILE_MASK)) ||
        (clp->seqstat == SENT && (mandatory_seqstats & SENT_MASK)) ||
        (clp->seqstat == READY && (mandatory_seqstats & READY_MASK)) ||
        (clp->seqstat == SHOTGUN && (mandatory_seqstats & SHOTGUN_MASK)) ||
        (clp->seqstat == FINISHED && (mandatory_seqstats & FINISHED_MASK)) ||
        (clp->seqstat == SD && (mandatory_seqstats & SD_MASK)))
    {
        return 1;
    }
    return 0;
}
/* WMN added to init the contig and clone id arrays */
/* 1/2/07 this had a problem because it used max_contig
  and ignored MAXCTGS. Now most of the init is done in 
    get_ctg_id */
/* Note that this is called both before pick and before mtp */
void
init_ids(){
  int i;
  CLONE *clp1;
  struct contig *cptr1;
  int ctgID;

  for (i=1; i<=max_contig; i++) {
    if (MaxCtgClones < contigs[i].count)
        MaxCtgClones = contigs[i].count;
  }
  for (i=0; i<MAXCTGS; i++) {
    clonekey[i]  = 0;
    num_clones[i] = 0;
  }
  num_ctgs = 0; /*WMN this was not getting reset*/

  for(i=1; i<=max_contig; i++){

    /* WMN 2 lines added 5/19/06 to prevent error msgs on empty contigs */
    if(run_on_single_ctg && i != selected_ctg) continue; 
    if(contigs[i].count==0) continue;

    find_Clone(i);


    ctgID = get_ctg_id(i);

    for(cptr1=root; cptr1->new!=NULL; cptr1=cptr1->new){
      clp1=arrp(acedata, cptr1->next, CLONE);
      get_clone_id(ctgID, clp1->clone);

       }
    
    }
}


/*                     DEF: find_fp_pairs
 * Main loop for finding fingerprint-based pairs. First, we find pair
 * candidates based of overlap in FPC. Next, we either confirm or
 * reject the candidates based on fingerprint comparisons. This is
 * done in several steps. First, we find a spanner and see if the
 * number of bands shared by the candidate pair is acceptable, and
 * most (or all) of the spanner's bands are accounted for. If so, we
 * try to find left- and right-flanking clones to account for the
 * unique bands (not shared with spanner) in the pair candidate. If we
 * have no mismatches, we quit and add the pair to the 'pairs'
 * structure, since this is the best we can do. Otherwise, we keep
 * looking. If there are several pair/spanner/flanker combinations
 * meeting the criteria set by the user, the best one is picked after
 * all have been examined (provided none has 0 mismatches).*/
/* cari 3 feb 05 - add return code */
static int
find_fp_pairs(){
  int i, j;
  CLONE *clp1, *clp2, *clpL, *clpR;
  struct contig *cptr1, *cptr2,
    *cur_span=NULL, *cur_lflank=NULL, *cur_rflank=NULL,
    *best_lflank=NULL, *best_rflank=NULL,
    *overall_best_left=NULL, *overall_best_right=NULL,
    *overall_best_span=NULL, *overall_best_lflank=NULL,
    *overall_best_rflank=NULL, *first_lflank=NULL, *last_lflank=NULL,
    *first_rflank=NULL, *last_rflank=NULL, *left_fl, *right_fl;
  int cb_olap;
  int pair_midpt;
  struct spanner span_candidates[CANDIDATE];
  int cur_span_ind=-1;
  int num_span_candidates=0;
  int have_good_spanner, have_good_lflank, have_good_rflank;
  int find_new_spanner=FALSE;
  int tried_all;
  int fail_code;
  struct pair_bin bin_values, overall_best_bin_values;
  int best_lflank_mismatch, best_rflank_mismatch;
  int best_mismatch_sum, overall_best_mismatch_sum;
  int sizeL, sizeR;
  int sizeL_from_file, sizeR_from_file;
  int total_pairs=0;
  char str1[MAXPATHLEN+100];
  int have_sizes_dir=FALSE;
  int zero_pairs=0, shared_num;
  GArray *mandatory;
  int skip_contig = 0;  /* part of changes 5/19/06 for skipping contigs w/too many spanner */

  struct contig *root_right;
  int shared_bands, left_unacc, right_unacc, span_mismatch, score, max_score=0;

  if (!dataloaded) return 0;                      /* Must have project loaded*/
  if (!arrayExists(bands)){                     /* Read cor file if necessary*/
    if (fpRead() == -1) {
      displaymess("No cor file - no analysis");
      return 0;
    }
  }

  hitCR();
  printf("Find Fingerprints Pairs\n");

  if(ctg_window!=NULL) gtk_widget_destroy(ctg_window);

  if(strlen(dirName)>0) sprintf(str1,"%s/Sizes",dirName);
  else sprintf(str1,"./Sizes");
  if(filCheck(str1,"d") && Use_sizes) have_sizes_dir=TRUE;

  mandatory = g_array_new(FALSE, FALSE, sizeof(gint));

  for(i=1; i<=max_contig; i++){

    if(run_on_single_ctg && i != selected_ctg) continue;
    if(contigs[i].count==0) continue;
	if (contigs[i].ctgstat== DEAD || contigs[i].ctgstat == AVOID) continue;

    skip_contig = 0;

    g_array_set_size(mandatory, 0);
    /* cari 3 feb 05 - added (clones) */
    printf("Clone pairs for ctg%d (clones %d)...", i, contigs[i].count);
    fflush(stdout);
    find_Clone(i);

/* Jingmei Sep. 05 - added for ordered clone list based on right end */
    root_right = (struct contig *)messalloc((sizeof(struct contig)*contigs[i].count));
    memcpy(root_right, root, sizeof(struct contig)*contigs[i].count);
    orderclonesRight(i, root_right);

    orderclones(i);

    /* Loop over all clones in contig quadratically*/
    for(cptr1=root; cptr1->new!=NULL; cptr1=cptr1->new){
      clp1=arrp(acedata, cptr1->next, CLONE);
      if (clp1->seqstat == SD) // ignore SD clones
          continue;
      if (use_mandatory(clp1)) {
          g_array_append_val(mandatory, cptr1->next);
      }
      for(cptr2=cptr1->new; cptr2!=NULL; cptr2=cptr2->new){
          clp2=arrp(acedata, cptr2->next, CLONE);
          if (NULL != find_pair(i, clp1->clone, clp2->clone) ||
            NULL != find_pair(i, clp2->clone, clp1->clone) ) {
             continue;
          }


          if (clp2->seqstat == SD) // ignore SD
              continue;
          // clones at this point have no seqstat
          if((clp1->x < clp2->x) && (clp1->y < clp2->y)){
              cb_olap=clp1->y - clp2->x + 1;
              if((cb_olap >= minOlap) && (cb_olap <= maxOlap)){
                  /* We have an overlap in the acceptable range*/
                  shared_num = check_fp_shared(cptr1->next, cptr2->next);
                  if(shared_num < minShared) continue;

                  fail_code=INT_MAX;
                  have_good_spanner=have_good_lflank=have_good_rflank=tried_all=FALSE;
                  //pair_midpt = abs(clp1->y - clp2->x)/2 + MIN(clp2->x, clp1->y);
                  // The following is equivalent to the above, but simpler. MP
                  pair_midpt = (clp1->y + clp2->x) / 2;
                  cur_span=NULL;
                  overall_best_mismatch_sum=INT_MAX;
                  while(fail_code && !tried_all){
                      find_new_spanner=FALSE;
                      if(!tried_all && !have_good_spanner){
                          /* Try to find spanner*/
                          if(cur_span==NULL){
                              cur_span_ind=0;
                              num_span_candidates=
                                  get_span_candidates(cptr1, cptr2, pair_midpt,
                                                      span_candidates);
                              if (num_span_candidates >= CANDIDATE) {
                                 printf("Aborting contig\n"); fflush(0); 
                                 skip_contig = 1;
                                 break;
                              }
                              qsort(span_candidates, num_span_candidates,
                                    sizeof(struct spanner),
                                    (int (*)(const void*, const void*))sortSpanners);
                              if(num_span_candidates>0)
                                  cur_span=span_candidates[cur_span_ind++].cptrspan;
                              else 
                                  tried_all=TRUE;
                              
                          }
                          else if(cur_span_ind < num_span_candidates)
                              cur_span=span_candidates[cur_span_ind++].cptrspan;
                          else tried_all=TRUE;
                      }
                      if(have_good_spanner){
                          /* Now that we have a good spanner, look for good flankers*/
                          /* Jingmei Sep. 05 major change for flankers */
                          cur_lflank=cur_rflank=NULL;
                          best_lflank_mismatch=best_rflank_mismatch=INT_MAX;
                          first_lflank = last_lflank = first_rflank = last_rflank =  NULL;
                          get_leftflank_candidates(root_right, cptr1, cptr2, 
                                   clp1->x+minOlap, clp1->y-minOlap, &first_lflank,
                                                   &last_lflank);
                          get_rightflank_candidates(cptr1, cptr2, clp2->x+minOlap, 
                                   clp2->y-minOlap, &first_rflank, &last_rflank);

                          if(first_lflank!=NULL && first_rflank!=NULL) {
                              for(left_fl=first_lflank; left_fl!=last_lflank; left_fl=left_fl->new){
                                  if (left_fl->next != cptr1->next && left_fl->next != cur_span->next) {
                                      cur_lflank=left_fl;

                                      fail_code=check_fp_integrity(cptr1->next, cptr2->next,
                                                                   cur_span->next,
                                                                   cur_lflank->next,
                                                                   -1,
                                                                   &bin_values);

                                      if(bin_values.flank_L_mis < best_lflank_mismatch){
                                          best_lflank_mismatch=bin_values.flank_L_mis;
                                          best_lflank=cur_lflank;
                                      }
                                      if(!(fail_code & HAVE_LFLANK_MISMATCH_MASK))
                                          /* Best we can do*/
                                          break;
                                  }
                              }
                              for(right_fl=first_rflank; right_fl!=last_rflank; right_fl=right_fl->new) {
                                  if (right_fl->next != cptr2->next && right_fl->next != cur_span->next) {
                                      cur_rflank = right_fl;
                                      fail_code=check_fp_integrity(cptr1->next, cptr2->next,
                                                                   cur_span->next,
                                                                   -1,
                                                                   cur_rflank->next,
                                                                   &bin_values);
                                      if(bin_values.flank_R_mis < best_rflank_mismatch){
                                          best_rflank_mismatch=bin_values.flank_R_mis;
                                          best_rflank=cur_rflank;
                                      }
                                      if(!(fail_code & HAVE_RFLANK_MISMATCH_MASK))
                                          /* Best we can do*/
                                          break;
                                  }
                              }
                          }
                          tried_all = TRUE;
                          if(best_lflank_mismatch<INT_MAX &&
                             best_rflank_mismatch<INT_MAX){
                              best_mismatch_sum= best_lflank_mismatch+best_rflank_mismatch+
                                  bin_values.span_mis;
                              if(best_mismatch_sum < overall_best_mismatch_sum){
                                  overall_best_mismatch_sum=best_mismatch_sum;
                                  check_fp_integrity(cptr1->next, cptr2->next,
                                                     cur_span->next, best_lflank->next,
                                                     best_rflank->next, &bin_values);
                                  overall_best_left = cptr1;
                                  overall_best_right = cptr2;
                                  overall_best_span=cur_span;
                                  overall_best_lflank=best_lflank;
                                  overall_best_rflank=best_rflank;
                                  overall_best_bin_values=bin_values;
                              }
                          } 
                          if(tried_all) find_new_spanner=TRUE;
                      }
                      if(!tried_all && fail_code){
                          fail_code=check_fp_integrity(cptr1->next, cptr2->next,
                                                       cur_span->next, -1, -1,
                                                       &bin_values);
                          if(fail_code & (MIN_BAND_MASK | MAX_BAND_MASK))
                              /*This pair shares too many or not enough bands*/
                              tried_all=TRUE;
                              
                          if(!(fail_code & SPAN_FAILURE_MASK))
                              have_good_spanner=TRUE;
                      }
                      if(find_new_spanner){
                          have_good_spanner=have_good_lflank=have_good_rflank=FALSE;
                          tried_all=FALSE;
                      }
                  }

                  clpL=arrp(acedata, cptr1->next, CLONE);
                  clpR=arrp(acedata, cptr2->next, CLONE);
                  sizeL=sizeR=0;
                  sizeL_from_file=sizeR_from_file=FALSE;
                  if(have_sizes_dir){
                      sizeL=GetSize(clpL);
                      sizeR=GetSize(clpR);
                  }
                  if(sizeL==0)
                      sizeL=clpL->fp->b2*Proj.avgbandsize; /* cari 3 feb 05 - was 4096 */
                  else
                      sizeL_from_file=TRUE;

                  if(sizeR==0)
                      sizeR=clpR->fp->b2*Proj.avgbandsize; /* cari 3 feb 05 - was 4096*/
                  else
                      sizeR_from_file=TRUE;

                  if(overall_best_mismatch_sum != INT_MAX){
                      /* CAS recalulate the span_LR_share and find
                         corresponding sizes; Pz.useSz is used in
                         the loadSizeCz and will not load the
                         sizes unless this is set, so its also
                         used here to tell check_fp_intgrity to
                         determine sizes */
                      if (sizeL_from_file) {
                          Pz.useSz=1;
                          check_fp_integrity(overall_best_left->next,
                                             overall_best_right->next,
                                             overall_best_span->next,
                                             overall_best_lflank->next,
                                             overall_best_rflank->next,
                                             &bin_values);
                          Pz.useSz=0;
                      }
                      else
                          LR_overlap =
                              overall_best_bin_values.span_LR_share *
                              Proj.avgbandsize;

                      add_to_pairs(i, FINGERPRINT, clpL->clone, clpR->clone,0,
                                   arrp(acedata, overall_best_span->next,
                                        CLONE)->clone,
                                   arrp(acedata, overall_best_lflank->next,
                                        CLONE)->clone,
                                   arrp(acedata, overall_best_rflank->next,
                                        CLONE)->clone,
                                   clpL->x, clpL->y, clpR->x, clpR->y,
                                   overall_best_left->next, overall_best_right->next,
                                   overall_best_span->next,
                                   overall_best_lflank->next,
                                   overall_best_rflank->next,
                                   LR_overlap, -1, /* cari */
                                   sizeL, sizeR, sizeL_from_file, sizeR_from_file,
                                   &overall_best_bin_values);
                  } else {
                      add_to_pairs(i, FINGERPRINT, clpL->clone, clpR->clone,0,
                              "NoSpanner", "NoLflanker", "NoRflanker",    
                              clpL->x, clpL->y, clpR->x, clpR->y,
                              cptr1->next, cptr2->next,
                              -1, -1, -1, shared_num*Proj.avgbandsize, -1,  
                              sizeL, sizeR, sizeL_from_file, sizeR_from_file, NULL);
                  }
              }

          }
          if (skip_contig == 1) break;
          if(clp1->y - clp2->x < minOlap)
              break;  /*Can't possibly find any more good pairs*/
      }
      if (skip_contig == 1) break;
    }

    /* cari 3 feb 05 - added zero_pairs cnt */
    if(pair_cnt!=NULL){
      printf("%d pairs\n",pair_cnt[i]);
      total_pairs+=pair_cnt[i];
      if (pair_cnt[i]==0) zero_pairs++;
    }
    else {
      printf("0 pairs\n");
      zero_pairs++;
    }

    if(graphInterruptCalled()){
      printf("Premature termination of 'Find overlapping pairs'!!\n");
      break;
    }
    messfree(root_right);
    root_right = 0;
  }

  for(i = 1; i <= max_contig; i++) {
    if(pair_cnt != NULL) {
      for(j = 0; j < pair_cnt[i]; j++) {
        if(pairs[i].p[j].pair_type == FINGERPRINT && strcmp(pairs[i].p[j].cspan, "NoSpanner")) { 
	  shared_bands = pairs[i].p[j].olap;
	  left_unacc = pairs[i].p[j].bin_values.flank_L_mis* Proj.avgbandsize;
	  right_unacc = pairs[i].p[j].bin_values.flank_R_mis* Proj.avgbandsize;
          span_mismatch = pairs[i].p[j].bin_values.span_mis*Proj.avgbandsize;
	  score = shared_bands + 2*(left_unacc + right_unacc) + 10*span_mismatch;
          pairs[i].p[j].weight_score = score;
          if(score > max_score) 
            max_score = score;
        }
      }
    }
  }

  for(i = 1; i <= max_contig; i++) {
    if(pair_cnt != NULL) {
      for(j = 0; j < pair_cnt[i]; j++) {
        if(pairs[i].p[j].pair_type == FINGERPRINT &&  !strcmp(pairs[i].p[j].cspan, "NoSpanner"))  
          pairs[i].p[j].weight_score = 2*max_score;
      }
    }
  }

  g_array_free(mandatory, TRUE);
  mandatory = 0;

  if (zero_pairs > 0) printf("Contigs with zero pairs %d\n",zero_pairs);
  printf("Identified %d fingerprint pairs\n\n", total_pairs);
  return total_pairs;
}


static void
browse_bss_file(void)
{
    GtkWidget* file_selector;
    FileSelectionData sdata_ok, sdata_cancel;
    const gchar bss_glob[] = "*.bss";
    gchar* bss_results;

    file_selector =
        gtk_file_selection_new("Please select a BSS file or directory");
    bss_results =
        g_strjoin(G_DIR_SEPARATOR_S, GETCURDIR, "BSS_results", "", NULL);
    gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_selector),
                                    bss_results);
    //gtk_file_selection_complete(GTK_FILE_SELECTION(file_selector), bss_glob);
    gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(file_selector));
    sdata_ok.name = NULL;
    sdata_ok.selector = file_selector;
    sdata_ok.button = OK;
    sdata_cancel.name = NULL;
    sdata_cancel.selector = file_selector;
    sdata_cancel.button = CANCEL;
    gtk_signal_connect(
        GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button),
        "clicked", GTK_SIGNAL_FUNC(file_selection_cb), &sdata_ok);
    gtk_signal_connect(
        GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button),
        "clicked", GTK_SIGNAL_FUNC(file_selection_cb), &sdata_cancel);
    gtk_widget_show(file_selector);
    gtk_main();
    if (sdata_ok.name != NULL) {
        strncpy(bssFileText, sdata_ok.name, sizeof(bssFileText));
        g_free(sdata_ok.name);
        sdata_ok.name = 0;
        bssFileText[sizeof(bssFileText) - 1] = '\0';
        if (strlen(bssFileText) >= sizeof(bss_glob) - 1 &&
            strcmp(bssFileText + strlen(bssFileText) - (sizeof(bss_glob) - 1),
                   "*.bss") == 0)
            bssFileText[strlen(bssFileText) - (sizeof(bss_glob) - 1)] = '\0';
    }
    g_free(bss_results);
    bss_results = 0;
    ZselectMTP();
}



/*                     DEF: print_pair_stats
 * Prints information about the pairs as they are stepped through.*/
static void
print_pair_stats(struct pair *p)
{
    char sizeLstr[20], sizeRstr[20], no[3] = "-";

    if (p->c1size_from_file)
        sprintf(sizeLstr,"%d*", p->c1size);
    else
        sprintf(sizeLstr,"%d", p->c1size);

    if (p->c2size_from_file)
        sprintf(sizeRstr,"%d*", p->c2size);
    else
        sprintf(sizeRstr,"%d", p->c2size);

    switch (p->pair_type) {
    case FINGERPRINT:
        sprintf(messageText2, "Size:%7s, %-7s Shared: %-2d  Mismatch: %d",
                sizeLstr, sizeRstr,
                p->bin_values.span_LR_share,
                p->bin_values.flank_L_mis + p->bin_values.span_mis +
                p->bin_values.flank_R_mis);
        Show;

        printf("\nFingerprint pair: olap %d\n",p->olap);
        printf("L-flank     Left        Spanner     Right       R-flank\n");
        printf("%-11s %-11s %-11s %-11s %-11s\n", p->clflank,
               p->c1, p->cspan, p->c2, p->crflank);
        printf("            %-23s %-23s (length)\n", sizeLstr, sizeRstr);
        printf("%-11d %-11d %-11d %-11d %-11d (shared)\n",
               p->bin_values.flank_L_share,
               p->bin_values.span_L_share, p->bin_values.span_LR_share,
               p->bin_values.span_R_share, p->bin_values.flank_R_share);
        printf("%-11s %-11d %-11d %-11d %-11s (mismatch)\n", no, p->bin_values.flank_L_mis,
               p->bin_values.span_mis, p->bin_values.flank_R_mis, no);
        break;

    case BSS_DRAFT:
        sprintf(messageText2, "Size:%7s, %-7s Seq Olap: %d",
                sizeLstr, sizeRstr, p->olap);
        Show;

        printf("\nBSS-draft based pair:\n");
        printf("Left        Right       Seq Olap    FPC Olap\n");
        printf("%-11s %-11s %-11d %-11d\n",
               p->c1, p->c2, p->olap, p->y1 - p->x2 + 1);
        printf("%-11s %-11s                          (length)\n", sizeLstr,
               sizeRstr);
        break;

    case EXP:
        sprintf(messageText2, "Size:%7s, %-7s Seq Olap: %d",
                sizeLstr, sizeRstr, p->olap);
        Show;

        printf("\nMTP junction:\n");
        printf("Left        Right       Seq Olap    FPC Olap\n");
        printf("%-11s %-11s %-11d %-11d\n",
               p->c1, p->c2, p->olap, p->y1 - p->x2 + 1);
        printf("%-11s %-11s                          (length)\n", sizeLstr,
               sizeRstr);
        break;
    default:
        g_assert_not_reached();
        break;
    }
}


/*                     DEF: clear_pair_highlight
 * Set the highcol variable for the current clone to zero,
 * so the colors get cleared the next time the contig display is redrawn*/
/* WMN 9/11/06 add checks in case there is no spanner etc. */
static int clear_pair_highlight(struct pair *p){
  arrp(acedata, p->index1, CLONE)->highcol=0;
  arrp(acedata, p->index2, CLONE)->highcol=0;
  if(p->pair_type==FINGERPRINT){
    if (p->indexspan >= 0) {
        arrp(acedata, p->indexspan, CLONE)->highcol=0;
    }
    if (p->indexlflank >= 0) {
        arrp(acedata, p->indexlflank, CLONE)->highcol=0;
    }
    if (p->indexrflank >= 0) {
        arrp(acedata, p->indexrflank, CLONE)->highcol=0;
    }
  }
  return 0;
}

static int clear_single_highlight(CLONE *clp) {
  clp->highcol = 0;
  return 0;
}

/*                     DEF: highlight_pair_clones
 * Highlight the pair, along with spanners and flankers for FP-based clones,
 * in the contig display.  The pair is blue, the spanner is paleblue, and the
 * flankers are palegray.*/
/* WMN 9/11/06 add checks in case there is no spanner etc. */
static void highlight_pair_clones(int contig, struct pair *p){
  CLONE *clp1, *clp2, *clpspan, *clplflank, *clprflank;

  clp1=arrp(acedata, p->index1, CLONE);
  clp2=arrp(acedata, p->index2, CLONE);
  clp1->highcol=BLUE;
  clp2->highcol=BLUE;
  if(p->pair_type==FINGERPRINT){
    if (p->indexspan >= 0) {
        clpspan=arrp(acedata, p->indexspan, CLONE);
        clpspan->highcol=PALEBLUE;
    }
    if (p->indexlflank >= 0) {
        clplflank=arrp(acedata, p->indexlflank, CLONE);
        clplflank->highcol=PALEGRAY;
    }
    if (p->indexrflank >= 0) {
        clprflank=arrp(acedata, p->indexrflank, CLONE);
        clprflank->highcol=PALEGRAY;
    }
  }
  centre_pos=clp1->y;
  if(ctg_window!=NULL && contig==currentctg) refresh_all_track_colors();
  else{ showburied=3; gtk_ctgdisplay(contig);}
  if(p->pair_type==FINGERPRINT){
    cloneindex[0]=p->indexlflank;
    cloneindex[1]=p->index1;
    cloneindex[2]=p->indexspan;
    cloneindex[3]=p->index2;
    cloneindex[4]=p->indexrflank;
    if(show_fp){
      if (!arrayExists(bands)){  /* Read cor file if necessary*/
        if (fpRead() == -1) {
          displaymess("No cor file - no analysis");
          return;
        }
      }
      displayFPmtp();
    }
  }
  gtk_idle_add((GtkFunction)clear_pair_highlight, p);
}

static void highlight_single_clone(int contig, CLONE *clp) {

  clp->highcol = BLUE;
  centre_pos=clp->y;
  if(ctg_window!=NULL && contig==currentctg) refresh_all_track_colors();
  else{ showburied=3; gtk_ctgdisplay(contig);}
  gtk_idle_add((GtkFunction)clear_single_highlight, clp);
}
  
/*                     DEF: find_bss_pairs
 * Calls function that computes BSS-draft based pairs (in pairs.c)*/
static int find_bss_pairs(){
  if(bssFileText[0]=='\0'){
    printf("You must select a BSS file first.\n");
    return 0;
  }
  hitCR();
  return compute_pairs(bssFileText);
}

/*                     DEF: next_pairs
 * Step forwards through pairs.*/
static void next_pairs(){
  if(!have_pairs){
    printf("Must run 'Find overlapping pairs' first\n");
    return;
  }

  hitCR();

  /* martin 14 feb 05, added test for NULL */
  if(pair_cnt == NULL || pair_cnt[ctg]==0){
    printf("No pairs for ctg%d\n", ctg);
    return;
  }

  if(ctg!=currentctg) cur_pair=cur_pick=-1;

  cur_pair++;

  if(cur_pair>=pair_cnt[ctg]){
    printf("End of contig reached; starting over.\n");
    cur_pair=0;
  }

  print_pair_stats(&(pairs[ctg].p[cur_pair]));
  highlight_pair_clones(ctg, &(pairs[ctg].p[cur_pair]));
}

/*                     DEF: pref_pairs
 * Step backwards through pairs.*/
static void prev_pairs(){
  if(!have_pairs){
    printf("Must run 'Find overlapping pairs' first\n");
    return;
  }

  hitCR();

  /* martin 14 feb 05, added test for NULL */
  if(pair_cnt == NULL || pair_cnt[ctg]==0){
    printf("No pairs for ctg%d\n", ctg);
    return;
  }

  if(ctg!=currentctg) cur_pair=cur_pick=-1;

  cur_pair--;

  if(cur_pair<0){
    printf("Beginning of contig reached; starting at rear.\n");
    cur_pair=pair_cnt[ctg]-1;
  }

  print_pair_stats(&(pairs[ctg].p[cur_pair]));
  highlight_pair_clones(ctg, &(pairs[ctg].p[cur_pair]));
}

/*                     DEF: print_pick_stats
 * Print expressway and pair information of picked MTP clones*/
static void
print_pick_stats(struct pick *p){

  sprintf(messageText, "Clones (%d, %d) in expressway of %d", p->exp_pos1,
          p->exp_pos2, p->exp_cnt);
  Show;
  printf("\n%s:\n",messageText);
  print_pair_stats(p->picked);
}

/*                     DEF: highlight_pick_clones
 * Highlight the picked pair*/
static void
highlight_pick_clones(int contig, struct pick *p){
  highlight_pair_clones(contig, p->picked);
}

/*                     DEF: pick_mtp_clones
 * Callback for 'Pick MTP clones'.  Calls function for picking
 * MTP clones from the pairs, which must have been found previously.*/
 void pick_mtp_clones(){

  if(!have_pairs){
    printf("You must run 'Find overlapping pairs' for the fingerprints first.\n");
    return;
  }
  if(have_picks){
    free_picks_mem();
    have_picks=FALSE;
    if (!Zbatch_flag)
        graphBoxDraw(picksBox, BLACK, WHITE);
  }
  if (!Zbatch_flag)
      hitCR();

  pick_exp_and_mtp();

  have_picks=TRUE;
  if (!Zbatch_flag)
      graphBoxDraw(picksBox, BLACK, LIGHTGRAY);
}

/*                     DEF: next_pick
 * Step forwards through picked MTP clones.*/
static void next_pick(){
  CLONE *clp;
  struct pick *p;
 
  if(!have_picks){
    printf("Must run 'Pick MTP clones' first\n");
    return;
  }

  hitCR();

  /* martin 14 feb 05, added test for NULL */
  if(ctg!=currentctg) cur_pair=cur_pick=-1;
  cur_pick++;

  if(pick_cnt != NULL && pick_cnt[ctg] != 0) {
    if(cur_pick>=pick_cnt[ctg]){
      printf("End of contig reached; starting over.\n");
      cur_pick=0;
    }
    
    p = &(picks[ctg].p[cur_pick]);
    if(p->picked->pair_type != SNG) {
      print_pick_stats(p);
      highlight_pick_clones(ctg, p);
    }
    else {
      clp=arrp(acedata, p->picked->index1, CLONE);
      printf("\nMTP clone: %s\n", clp->clone);
      printf("Size: %d\n", p->picked->c1size);
      highlight_single_clone(ctg, clp);
    }
  }
}

/*                     DEF: prev_pick
 * Step backwards through picked MTP clones.*/
static void prev_pick(){
  CLONE *clp;
  struct pick *p;

  if(!have_picks){
    printf("Must run 'Pick MTP clones' first\n");
    return;
  }

  hitCR();

  /* martin 14 feb 05, added test for NULL */
  if(ctg!=currentctg) cur_pair=cur_pick=-1;
  cur_pick--;

  if(pick_cnt != NULL && pick_cnt[ctg] != 0) {
    if(cur_pick<0){
      printf("Beginning of contig reached; starting at rear.\n");
      cur_pick=pick_cnt[ctg]-1;
    }

    p = &(picks[ctg].p[cur_pick]);
    if(p->picked->pair_type != SNG) {
      print_pick_stats(p);
      highlight_pick_clones(ctg, p);
    } else {
      clp=arrp(acedata, p->picked->index1, CLONE);
      printf("\nMTP clone: %s\n", clp->clone);
      printf("Size: %d\n", p->picked->c1size);
      highlight_single_clone(ctg, clp);
    }
  }
}

/*                     DEF: all_pick
 * Highlight all picked MTP clones.*/
static void all_pick(){
  int i;
  CLONE *clp;
  struct pick *p;

  if(!have_picks){
    printf("Must run 'Pick MTP clones' first\n");
    return;
  }

  hitCR();

  if(pick_cnt != NULL && pick_cnt[ctg] != 0) {
    for(i=0;i<pick_cnt[ctg];i++){
      p = &(picks[ctg].p[i]);
      if(p->picked->pair_type != SNG) {
        print_pick_stats(p);
        arrp(acedata, p->picked->index1, CLONE)->highcol=BLUE;
        arrp(acedata, p->picked->index2, CLONE)->highcol=BLUE;
      } else {
        clp=arrp(acedata, p->picked->index1, CLONE);
        clp->highcol = BLUE;
      }
      if(ctg_window!=NULL && ctg==currentctg) refresh_all_track_colors();
      else{ showburied=3; ctgdisplay(ctg);}
    }
  }
}

/*                     DEF: set_tile_ctg
 * Set all MTP clones' sequence status to TILE for the selected contig.*/
static int set_tile_ctg(){
  int i, cnt=0;
  CLONE *clp1, *clp2;
  char remark[100];
  void addremark();

  if(!have_picks || pick_cnt==NULL){
    printf("Must run 'Pick MTP clones' first\n");
    return 0;
  }

  for(i=0; i<pick_cnt[ctg]; i++){
      clp1 = arrp(acedata, picks[ctg].p[i].picked->index1, CLONE);
      clp2 = arrp(acedata, picks[ctg].p[i].picked->index2, CLONE);
      if (clp1->seqstat == 0) {
          clp1->seqstat=TILE;
          clp1->seqtype=HALFX;
          cnt++;
      }
      if(picks[ctg].p[i].exp_cnt != 1) {
        sprintf(remark,"MTP: %s %d", clp2->clone, picks[ctg].p[i].picked->olap);
        addremark(remark,  picks[ctg].p[i].picked->index1);
        if(clp1->parent != -1) unbury(picks[ctg].p[i].picked->index1);

        if (clp2->seqstat == 0) {
           clp2->seqstat=TILE;
           clp2->seqtype=HALFX;
           cnt++;
        }
        if(clp2->parent != -1) unbury(picks[ctg].p[i].picked->index2);
      }

      if (picks[ctg].p[i].exp_pos1 == 1) {
         addremark("MTP: expway start",  picks[ctg].p[i].picked->index1);  
      }
      if (picks[ctg].p[i].exp_pos2 == picks[ctg].p[i].exp_cnt) {
         addremark("MTP: expway end",  picks[ctg].p[i].picked->index2);  
      }
  }
  if(ctg==currentctg) refresh_gtk_ctgdisplay();
return cnt;
}

static void set_tile_ctg_only()
{
   hitCR();
   printf("Set %d clones to TILE for contig %d\n",set_tile_ctg(), ctg);
   updateproj();
}

/*                     DEF: set_tile_all
 * Set all MTP clones' sequence status to TILE for all contigs.*/
static void set_tile_all(){
  int cnt=0, i, save_ctg;

  if(!have_picks){
    printf("Must run 'Pick MTP clones' first\n");
    return;
  }

  save_ctg=ctg;

  for(i=1; i<=max_contig; i++){
    if(contigs[i].count>0){
      ctg = i;
      cnt += set_tile_ctg();
    }
  }
  printf("Done setting %d MTP clones to status TILE.\n", cnt);
  ctg=save_ctg;
  updateproj();
}
/*                     DEF: clear_tile
 * clear all clones with status of  TILE for all contigs.*/
static void clear_tile()
{
int i, cnt=0;
CLONE *clone;
struct remark *fp,*prev;

    for (i=0; i<arrayMax(acedata); i++) {
       clone = arrp(acedata, i, CLONE);
       if (clone->seqstat==TILE) {
           clone->seqstat = clone->seqtype = 0;
           cnt++;
           prev=NULL;
           for (fp = clone->remark; fp != NULL; fp = fp->next)
           {
              if (strstr(fp->message,"MTP:")) 
              {
                 if(fp->next == NULL){ 
                    if (prev == NULL) clone->remark = NULL;
                    else prev->next = NULL;
                 }
                 else if (prev == NULL)  clone->remark = fp->next;
                 else prev->next = fp->next;
              }
              else prev = fp;
           }
       }
    }
    printf("Clear TILE sequencing status for %d clones\n",cnt);
    updateproj();
}

static int was_mandatory (int idx)
{
   CLONE *cln;
   cln = arrp(acedata, idx, CLONE);
   return use_mandatory(cln);
}

/*                     DEF: write_picked
 * Write MTP clones to file.*/
 void write_picked(){
  FILE *fp;
  char temp_dirName[MAXPATHLEN+1];
  char temp_fileName[MAXPATHLEN+1];
  char tempclone[CLONE_SZ];
  char lastclone[CLONE_SZ];
  int i,j, lastsize;

  if(!have_picks){
    printf("Must run 'Pick MTP clones' first\n");
    return;
  }
  if (pick_cnt == NULL) {
     fprintf(stderr, "No MTP selected\n");
     return;
  }

  if (!Zbatch_flag) {
      strcpy(temp_dirName, GETCURDIR);
      strcpy(temp_fileName, "mtp");
      if ((fp = (FILE *)graphQueryOpen(temp_dirName, temp_fileName, "txt","w",
                                       "Save pairs results as")) == NULL)
          return;
      printf("Writing %s/%s.txt...", temp_dirName, temp_fileName);fflush(0);
  }
  else if (strlen(mtp_output_file) > 0)
  {
		fp = fopen(mtp_output_file, "w");
  }
  else {
      fp = stdout;

  }
  mtpParameters(fp);

    fprintf(fp, "%-18s %-8s %-18s %-8s %-12s %-18s %-18s %-18s\n",
            "// MTP: Left Clone","Size","Right Clone","Overlap",
            "Type","Left BES","Right BES","Seq ctg"); 
  //fprintf(fp,"// MTP:  Clone Size    Right Overlap\n");
  fprintf(fp,"// * mandatory clone  Overlap=#bands * %d\n", Proj.avgbandsize);
  fflush(stdout);

  for(i=1; i<=max_contig; i++){
       if(contigs[i].count==0) continue;
       if (pick_cnt[i]==0) continue;

       fprintf(fp, "\nCTG%d\n",i);

       for(j=0; j<pick_cnt[i]; j++){

          strcpy(tempclone,picks[i].p[j].picked->c1);          
          if (was_mandatory(picks[i].p[j].picked->index1)) {
              strcat(tempclone,"*");            
          }
          if (picks[i].p[j].picked->pair_type == FINGERPRINT) {
            fprintf(fp, "%-18s %-8d %-18s %-8d %-12s", tempclone,
                  picks[i].p[j].picked->c1size,  picks[i].p[j].picked->c2,
                  picks[i].p[j].picked->olap,"FP");
          } else if (picks[i].p[j].picked->pair_type == BSS_DRAFT) {
            fprintf(fp, "%-18s %-8d %-18s %-8d %-12s %-18s %-18s %-18s", 
                  tempclone,
                  picks[i].p[j].picked->c1size,  picks[i].p[j].picked->c2,
                  picks[i].p[j].picked->olap, "BSS",picks[i].p[j].picked->clflank,
                  picks[i].p[j].picked->crflank, 
					picks[i].p[j].picked->draft_clone);
          } else if (picks[i].p[j].picked->pair_type == EXP) {
            if (picks[i].p[j].picked->olap >= 0) {
                fprintf(fp, "%-18s %-8d %-18s %-8d %-12s", 
                      tempclone,
                      picks[i].p[j].picked->c1size,  picks[i].p[j].picked->c2,
                      picks[i].p[j].picked->olap,"EXP_JCT");
                }
            else {
                fprintf(fp, "%-18s %-8d %-18s %-8d %-12s", 
                      tempclone,
                      picks[i].p[j].picked->c1size,  picks[i].p[j].picked->c2,
                      picks[i].p[j].picked->olap,"EXP_GAP");
                }
          } else if(picks[i].p[j].picked->pair_type == SNG) 
            fprintf(fp, "%-18s %-8d", tempclone, picks[i].p[j].picked->c1size);

          fprintf(fp, "\n");
          if(picks[i].p[j].picked->pair_type != SNG) {
            strcpy(lastclone, picks[i].p[j].picked->c2);
            lastsize =  picks[i].p[j].picked->c2size;
            if (was_mandatory(picks[i].p[j].picked->index2)) {
              strcat(lastclone,"*");                
            }
          } else 
            lastsize = -1;
       }
       if(lastsize != -1) 
         fprintf(fp, "%-18s %-8d\n", lastclone, lastsize);
  }
  if (!Zbatch_flag)
      fclose(fp);
  printf("done.\n");
}

/*                     DEF: show_mtp_help
 * Display help for the 'Select MTP' window*/
static void show_mtp_help(){
  show_help("Select MTP Help", "selectMTPhelp");
}

/*                     DEF: show_adv_help
 * Display help for the 'Mandatory clones' window*/
static void show_mandatory_clones_help(){
  show_help("Mandatory Clones Help", "mandatoryClonesMTPhelp");
}
/*                     DEF: show_adv_help
 * Display help for the 'Advanced settings' window*/
static void show_adv_help(){
  show_help("Advanced MTP Settings Help", "advancedBSSMTPhelp");
}

/*                     DEF: find_pairs_callback
 * Calls functions that find fingerprint-based pairs, BSS-draft based pairs,
 * or both, depending on the options that are turned on.*/
 void
find_pairs_callback(){
  int i;
  FILE* f;
  
  if (Zbatch_flag)
      f = stderr;
  else
      f = stdout;

  if(!(use_fp_pairs || use_bss_pairs)){
      fprintf(f, "You must select pair source ('Use fingerprints' or 'Use BSS results')\n");
    return;
  }

  if(!Zbatch_flag && !confirm_overwrite()) return;

  
  printf("********** Find overlapping pairs ***********\n");

  init_ids();

  have_pairs=FALSE;
  have_picks=FALSE;
  if (!Zbatch_flag) {
      graphBoxDraw(pairsBox, BLACK, WHITE);
      graphBoxDraw(picksBox, BLACK, WHITE);
  }

  if (use_bss_pairs) {
      if (Zbatch_flag)
          printf("Starting BSS draft pair computations\n");
      if(!find_bss_pairs()) return;
  }
  if (use_fp_pairs) {
      if (Zbatch_flag)
          printf("Starting fingerprint pair computations\n");
      if (!find_fp_pairs()) return;  /* cari 3 feb 05 */
  }

  if (pair_cnt != NULL) { /* martin 14 feb 05 */
    for(i=0; i<=max_contig; i++)
      qsort(pairs[i].p, pair_cnt[i], sizeof(struct pair), (void *)sortPairs);
  }

  have_pairs=TRUE;
  if (!Zbatch_flag)
      graphBoxDraw(pairsBox, BLACK, LIGHTGRAY);

  pairsParameters(stdout);
  printf("********** Finish overlapping pairs ***********\n");
}

/*                     DEF: load_pairs_file
 * Load pairs that have been previously computed and saved to a file.*/
static void
load_pairs_file(void)
{
    FILE *fp;
    char str[MAXPATHLEN+15];
    char oneline[1024] = "";
    int c;
    char c1[CLONE_SZ+1];
    char c2[CLONE_SZ+1];
    char cspan[CLONE_SZ+1];
    char clflank[CLONE_SZ+1];
    char crflank[CLONE_SZ+1];
    char draft_clone[CLONE_SZ+1];
    int x1, y1, x2, y2;
    int index1;
    int index2;
    int indexspan;
    int indexlflank;
    int indexrflank;
    int olap = 0, score;
    struct pair_bin bin_values;
    int fp_pairs = 0, bss_pairs = 0, mandatory_pairs = 0;
    int sizeL, sizeR;
    int sizeL_from_file, sizeR_from_file;
    int start_picks = FALSE;
    int exp_pos1, exp_pos2, exp_cnt, ljunction, rjunction;
    struct pair *picked_pair;
    int num_picks = 0;
    int cnt_ctg=0;

    have_pairs = FALSE;
    have_picks = FALSE;
    graphBoxDraw(pairsBox, BLACK, WHITE);
    graphBoxDraw(picksBox, BLACK, WHITE);

    if ((fp = fopen(pairsFileText, "r")) == NULL) {
        sprintf(str, "Could not open pairs file %s", pairsFileText);
        perror(str);
        return;
    }
    printf("\nLoading %s\n",pairsFileText);
    while (fgets(oneline,1024, fp) != NULL) {
       if (oneline[0] != '/') break;
       printf("%s",oneline);
    }
    if (feof(fp)) goto read_error;

    while (!feof(fp) && !start_picks) {
        if (FSCANLINE(fp, oneline) < 1)
            goto read_error;
        if (sscanf(oneline, "Ctg%d", &c) == 1)
            cnt_ctg++;
        else if (!strncmp(oneline, "FINGERPRINT", 11)) {
            if (sscanf(oneline,
                      "FINGERPRINT %s %d %d %d %d %s %d %d %d %d %d %d "
                      "%s %s %s %d %d %d %d %d %d %d %d",
                      c1, &x1, &y1, &sizeL, &sizeL_from_file,
                      c2, &x2, &y2, &sizeR, &sizeR_from_file,
                      &olap, &score, cspan, clflank, crflank,  
                      &(bin_values.span_L_share), &(bin_values.span_LR_share),
                      &(bin_values.span_R_share), &(bin_values.flank_L_share),
                      &(bin_values.flank_R_share), &(bin_values.span_mis),
                      &(bin_values.flank_L_mis),
                      &(bin_values.flank_R_mis)) != 23)
                goto read_error;
            if (!fppFind(acedata, c1, &index1, cloneOrder)) {
                printf("WARNING: %s in pairs file not in FPC!!\n", c1);
                continue;
            }
            if (!fppFind(acedata, c2, &index2, cloneOrder)) {
                printf("WARNING: %s in pairs file not in FPC!!\n", c2);
                continue;
            }
            /* WMN 9/11/06 these were not getting set on loading pair file */
            indexspan = indexrflank = indexlflank = -1;
            if (0 != strcasecmp(cspan,"Nospanner") && !fppFind(acedata, cspan, &indexspan, cloneOrder)) {
                printf("WARNING: spanner %s in pairs file not in FPC!!\n", cspan);
                continue;
            }
            if (0 != strcasecmp(clflank,"Nolflanker") && !fppFind(acedata, clflank, &indexlflank, cloneOrder)) {
                printf("WARNING: L flanker %s in pairs file not in FPC!!\n", clflank);
                continue;
            }
            if (0 != strcasecmp(crflank,"Norflanker") && !fppFind(acedata, crflank, &indexrflank, cloneOrder)) {
                printf("WARNING: R flanker %s in pairs file not in FPC!!\n", crflank);
                continue;
            }
            add_to_pairs(c, FINGERPRINT, c1, c2,0, cspan, clflank, crflank,
                         x1, y1, x2, y2, index1, index2, indexspan,
                         indexlflank, indexrflank, olap, score, sizeL, sizeR,
                         sizeL_from_file, sizeR_from_file, &bin_values);
            fp_pairs++;
        }
        else if (!strncmp(oneline, "BSS_DRAFT", 9)) {
            if (sscanf(oneline, "BSS_DRAFT %s %d %d %d %d %s %d %d %d %d %d %d %s %s %s",
                      c1, &x1, &y1, &sizeL, &sizeL_from_file,
                      c2, &x2, &y2, &sizeR, &sizeR_from_file, &olap, &indexspan,
                      clflank, crflank, draft_clone) != 15)
                goto read_error;
            if (!fppFind(acedata, c1, &index1, cloneOrder)) {
                printf("WARNING: %s in pairs file not in FPC!!\n", c1);
                continue;
            }
            if (!fppFind(acedata, c2, &index2, cloneOrder)) {
                printf("WARNING: %s in pairs file not in FPC!!\n", c2);
                continue;
            }

            add_to_pairs(c, BSS_DRAFT, c1, c2, draft_clone,NULL, clflank, crflank,
                         x1, y1, x2, y2, index1, index2, indexspan, -1, -1,
                         olap, olap, sizeL, sizeR,
                         sizeL_from_file, sizeR_from_file, NULL);
            bss_pairs++;
        }
        else if (!strncmp(oneline, "MTPpairs", 8))
            start_picks = TRUE;

/* cari 3 feb 05 - changed \n to \r */
        if (((fp_pairs + bss_pairs + mandatory_pairs + 1)
             % 1000) == 0)
            printf("Loading pair %d ......\r",
                   fp_pairs + bss_pairs + mandatory_pairs);
    }

    printf("Loaded %d fingerprint-based pairs and %d BSS-based pairs\n",
                 fp_pairs, bss_pairs);
    if (fp_pairs + bss_pairs + mandatory_pairs> 0) {
        have_pairs = TRUE;
        graphBoxDraw(pairsBox, BLACK, LIGHTGRAY);
    }

    if (start_picks) { 
        /* MTP clones were written to the file as well*/
        printf("Loading MTP clones ......");
        fflush(stdout);
        while (!feof(fp)) {
            if (FSCANLINE(fp, oneline) < 1)
                goto read_error;
            if (sscanf(oneline, "Ctg%d", &c) == 1)
                ;
            else if (sscanf(oneline, "%s %s %d %d %d %d %d", c1, c2, &exp_pos1,
                           &exp_pos2, &exp_cnt, &ljunction, &rjunction) == 7) {
                picked_pair = find_pair(c, c1, c2);
                if (picked_pair == NULL) {
                    printf("WARNING:  Pair (%s, %s) not found in ctg%d\n",
                           c1, c2, c);
                    continue;
                }
                add_to_picks(c, picked_pair, exp_pos1, exp_pos2, exp_cnt,
                             ljunction, rjunction);
                num_picks++;
            }
            else goto read_error;
        }
        if (num_picks > 0) {
            have_picks = TRUE;
            graphBoxDraw(picksBox, BLACK, LIGHTGRAY);
        }
        printf("%d picked pairs\n", num_picks);
    }

    fclose(fp);
    return;

 read_error:
    g_snprintf(str, 1023, "Error occured while reading %s", pairsFileText);
    perror(str);
    printf("Last line successfully read: %s\n",oneline);
    fclose(fp);
}

/*                     DEF: get_pairs_file_name_by_query
 * Query user for pairs file to load, and load it if valid file.*/
static void
get_pairs_file_name_by_query(){
  FILE *fp;
  char temp_dirName[MAXPATHLEN+1];
  char temp_fileName[MAXPATHLEN+1];

  if(!confirm_overwrite()) return;

  have_pairs=FALSE;
  have_picks=FALSE;
  graphBoxDraw(pairsBox, BLACK, WHITE);
  graphBoxDraw(picksBox, BLACK, WHITE);

  strcpy(temp_dirName, GETCURDIR);
  strcpy(temp_fileName, "pairs");
  if((fp = (FILE *)graphQueryOpen(temp_dirName, temp_fileName, "txt","r",
                                  "Load pairs file")) == NULL){
    return;
  }
  fclose(fp);

  sprintf(pairsFileText, "%s/%s", temp_dirName, temp_fileName);
  ZselectMTP();
  load_pairs_file();
}

/*                     DEF: get_pairs_file_name_from_text_box
 * Scan text box for pairs file name, and load it if valid file.*/
static void
get_pairs_file_name_from_text_box(){
  if(!confirm_overwrite()) return;

  have_pairs=FALSE;
  have_picks=FALSE;
  graphBoxDraw(pairsBox, BLACK, WHITE);
  graphBoxDraw(picksBox, BLACK, WHITE);

  load_pairs_file();
}

/*                     DEF: save_pairs_file
 * Write the current set of pairs to a file.*/
 void
save_pairs_file(void)
{
    FILE *fp;
    char temp_dirName[MAXPATHLEN+1];
    char temp_fileName[MAXPATHLEN+1];
    int i, j;

    strcpy(temp_dirName, GETCURDIR);
    strcpy(temp_fileName, "pairs");

	if (!Zbatch_flag)
	{
   		 fp = (FILE *)graphQueryOpen(temp_dirName, temp_fileName, "txt","w",
                                "Save pairs results as");
	}
	else if (strlen(pair_output_file) > 0)
	{
		fp = fopen(pair_output_file,"w");
	}
    if (fp == NULL)
        return;

    printf("Writing pairs to %s/%s.txt...", temp_dirName, temp_fileName);
    fflush(stdout);
    pairsParameters(fp);

    fprintf(fp,"c1 x1 y1 c2 x2 y2 olap cspan clflank crflank "
            "span_L_share span_LR_share span_R_share flank_L_share "
            "flank_R_share span_mis flank_L_mis flank_R_mis seqctg\n");
    if (pair_cnt != NULL) { /* martin 14 feb 05 */
        for (i = 1; i <= max_contig; i++) {
            if (contigs[i].count > 0) {
                fprintf(fp, "Ctg%d\n", i);
                for (j = 0; j < pair_cnt[i]; j++) {
                    switch (pairs[i].p[j].pair_type) {
                    case BSS_DRAFT:
                        fprintf(fp,
                                "BSS_DRAFT %s %d %d %d %d %s %d %d %d %d %d %d %s %s %s\n",
                                pairs[i].p[j].c1,
                                pairs[i].p[j].x1, pairs[i].p[j].y1,
                                pairs[i].p[j].c1size,
                                pairs[i].p[j].c1size_from_file,
                                pairs[i].p[j].c2,
                                pairs[i].p[j].x2, pairs[i].p[j].y2,
                                pairs[i].p[j].c2size,
                                pairs[i].p[j].c2size_from_file,
                                pairs[i].p[j].olap,
                                pairs[i].p[j].indexspan,
                                pairs[i].p[j].clflank,
                                pairs[i].p[j].crflank,
                                pairs[i].p[j].draft_clone
								);
                        break;

                    case FINGERPRINT:
                        if(strcmp(pairs[i].p[j].cspan, "NoSpanner")) {
                          fprintf(fp,
                                "FINGERPRINT %s %d %d %d %d %s %d %d %d %d "
                                "%d %d %s %s %s %d %d %d %d %d %d %d %d N/A\n",
                                pairs[i].p[j].c1,
                                pairs[i].p[j].x1, pairs[i].p[j].y1,
                                pairs[i].p[j].c1size,
                                pairs[i].p[j].c1size_from_file,
                                pairs[i].p[j].c2,
                                pairs[i].p[j].x2, pairs[i].p[j].y2,
                                pairs[i].p[j].c2size,
                                pairs[i].p[j].c2size_from_file,
                                pairs[i].p[j].olap,
                                pairs[i].p[j].weight_score,
                                pairs[i].p[j].cspan, pairs[i].p[j].clflank,
                                pairs[i].p[j].crflank,
                                pairs[i].p[j].bin_values.span_L_share,
                                pairs[i].p[j].bin_values.span_LR_share,
                                pairs[i].p[j].bin_values.span_R_share,
                                pairs[i].p[j].bin_values.flank_L_share,
                                pairs[i].p[j].bin_values.flank_R_share,
                                pairs[i].p[j].bin_values.span_mis,
                                pairs[i].p[j].bin_values.flank_L_mis,
                                pairs[i].p[j].bin_values.flank_R_mis);
                        } else {
                          fprintf(fp,
                                "FINGERPRINT %s %d %d %d %d %s %d %d %d %d "
                                "%d %d %s %s %s %d %d %d %d %d %d %d %d N/A\n",
                                pairs[i].p[j].c1,
                                pairs[i].p[j].x1, pairs[i].p[j].y1,
                                pairs[i].p[j].c1size,
                                pairs[i].p[j].c1size_from_file,
                                pairs[i].p[j].c2,
                                pairs[i].p[j].x2, pairs[i].p[j].y2,
                                pairs[i].p[j].c2size,
                                pairs[i].p[j].c2size_from_file,
                                pairs[i].p[j].olap,
                                pairs[i].p[j].weight_score,
                                pairs[i].p[j].cspan, pairs[i].p[j].clflank,
                                pairs[i].p[j].crflank,
                                0, 0, 0, 0, 0, 0, 0, 0); 
                        }
                        break;
                    default:
                        ; // we don't write EXP pairs
                        break;
                    }
                }
            }
        }
    }
    /* martin 14 feb 05, added test for NULL */
    if (have_picks && pick_cnt != NULL) {
        /* Also write picked pairs if we have them*/
        fprintf(fp, "\nMTPpairs\n\n");
        for (i = 1; i <= max_contig; i++) {
            if (contigs[i].count > 0) {
                fprintf(fp, "Ctg%d\n", i);
                for (j = 0; j < pick_cnt[i]; j++) {
                    fprintf(fp, "%s %s %d %d %d %d %d\n",
                            picks[i].p[j].picked->c1, picks[i].p[j].picked->c2,
                            picks[i].p[j].exp_pos1, picks[i].p[j].exp_pos2,
                            picks[i].p[j].exp_cnt,
                            picks[i].p[j].ljunction, picks[i].p[j].rjunction);
                }
            }
        }
    }

    fclose(fp);
    printf("done\n");
}

void pick_start(){
  pick_pair_start=!pick_pair_start;
  if (pick_pair_start)
    graphBoxDraw(pickStartBox, BLACK, RED);
  else
    graphBoxDraw(pickStartBox, BLACK, WHITE);
}

void move_to_pair(int index){
  int i, found=FALSE;

  if(!have_pairs){
    printf("Must run 'Find overlapping pairs' first\n");
    return;
  }

  /* martin 14 feb 05, added test for NULL */
  if (pair_cnt != NULL) {
    for(i=0;i<pair_cnt[ctg];i++){
      if((pairs[ctg].p[i].index1 == index) ||
         (pairs[ctg].p[i].index2 == index)){
        found=TRUE;
        break;
      }
    }
  }
  if(found){
    cur_pair=i-1;
    next_pairs();
  }
  else{
    messageText[0]='\0';
    strcpy(messageText2, "Sorry, no pairs for that clone.");
    Show;
    printf("%s\n", messageText2);
  }
}


/*********************************************************
                  MAIN: ZstepWindow
 The graphics for the Mini step window.
*********************************************************/
void ZstepWindow(){
  float row;
  static MENUOPT amenu[] = { {quitStep, "Close"},
                             { graphPrint,"Print Screen"},
                             { 0, 0 } };

  quitMTP();

  if(graphActivate(gStep)){
    graphPop();
  }
  else{
    gStep = graphCreate (TEXT_FIT,"Select MTP",.2,.2,.457,.160);
  }

  sprintf(contigText,"%d",ctg);

  graphClear();
  graphMenu(amenu);

  row = 1.0;
  graphButton("Full",ZselectMTP,1,row);
  graphText("Contig:",18,row);
  contigBox = graphTextEntry(contigText, 6, 26, row, (void *) hitCR2);

  row += 2.0;
  graphText("Step through Pairs:",1,row);
  graphButton("Next",next_pairs,23,row);
  graphButton("Previous",prev_pairs,29,row);
  pickStartBox = graphButton("Pick start",pick_start,39,row);
  if (pick_pair_start) graphBoxDraw(pickStartBox, BLACK, RED);
  else graphBoxDraw(pickStartBox, BLACK, WHITE);

  row += 2.0;
  graphText("Step through MTP:",1,row);
  graphButton("Next",next_pick,23,row);
  graphButton("Previous",prev_pick,29,row);
  graphButton("All",all_pick,39,row);

  row += 2.0;
  messageBox = graphBoxStart();
  graphTextPtr(messageText,1.0,row,49);
  graphBoxEnd();
  graphBoxDraw(messageBox,BLACK,CYAN);

  row += 2.0;
  messageBox2 = graphBoxStart();
  graphTextPtr(messageText2,1.0,row,49);
  graphBoxEnd();
  graphBoxDraw(messageBox2,BLACK,CYAN);

  graphRedraw();
}

/*********************************************************
                  MAIN: ZadvancedBSS
 The graphics for the BSS 'Advanced settings' window.
*********************************************************/
void ZadvancedBSS(){
  float row;
  static MENUOPT amenu[] = { {quitAdvancedBSS, "Close"},
                             { graphPrint,"Print Screen"},
                             { 0, 0 } };

  if(graphActivate(gAdvancedBSS)){
    graphPop();
  }
  else{
    gAdvancedBSS = graphCreate (TEXT_FIT,"Advanced settings",.2,.2,.330,.160);
    graphRegister (PICK, pickg2) ;
  }

  sprintf(maxSeqOlapText,"%d",max_seq_olap);
  sprintf(multCtgRatioText,"%d",mult_ctg_ratio);

  graphClear();
  graphMenu(amenu);

  row = 1.0;
  graphText("Maximum sequence overlap:",1,row);
  maxSeqOlapBox = graphTextEntry(maxSeqOlapText, 7, 28, row, hitCR3);

  row+=2.0;
  graphText("Multiple contig ratio:",1,row);
  multCtgRatioBox = graphTextEntry(multCtgRatioText, 2, 28, row, hitCR3);

  row+=2.0;
  graphText("Only positive overlaps",4,row);
  onlyPosArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (only_pos_olap) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(onlyPosArc, BLACK, TRANSPARENT);

  row+=2.0;
  graphText("Only single BES hits",4,row);
  onlySingleArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (only_single_bes) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(onlySingleArc, BLACK, TRANSPARENT);

  row+=2.0;
  graphButton("Close",quitAdvancedBSS,8,row);
  graphButton("MTP Help",show_adv_help,15,row);

  graphRedraw();
}

/*****************************************************************/
/*                  AceDB graphics callbacks                     */

void quitMTP(){
  pick_pair_start=FALSE;
  if(graphActivate(gMTP)){
    graphDestroy();
  }
  if(graphActivate(gStep)){
    graphDestroy();
  }
  if(graphActivate(gAdvancedBSS)){
    graphDestroy();
  }
}

void quitStep(){
  pick_pair_start=FALSE;
  if(graphActivate(gStep)){
    graphDestroy();
  }
}

void quitAdvancedBSS(){
  if(graphActivate(gAdvancedBSS)){
    hitCR3();
    graphDestroy();
  }
}

/*                DEF: pairsParmeters                    */
void pairsParameters(FILE *ptr) {
char tmp[25], tmp2[25];

  if (run_on_single_ctg) sprintf(tmp,"Contig %d",ctg);
  else strcpy(tmp, "All contigs");
  fprintf(ptr,"// %s  Min FPC overlap %d  Max FPC overlap %d\n", tmp, minOlap, maxOlap);

  if (use_fp_pairs) {
     if (Use_sizes) strcpy(tmp, "Use Sizes");
     else tmp[0] = '\0';
     fprintf(ptr,"// Use Fingerprints: Min Shared Bands %d  %s\n",  minShared, tmp);
  }
  if (use_bss_pairs) {
     fprintf(ptr,"// Use BSS: Score %d  Identity %d  File %s\n", minScore, minId, bssFileText);
     if (only_pos_olap) strcpy(tmp, "Only pos overlaps");
     else strcpy(tmp,"Allow neg overlaps"); 
     if (only_single_bes) strcpy(tmp2,"Only single BES hits");
     else strcpy(tmp2,"Allow mult BES hits");
     fprintf(ptr,"// Advanced:  Max Seq overlap %d  Mult contig ratio %d  %s  %s\n", 
                       max_seq_olap, mult_ctg_ratio, tmp, tmp2);
  }
}

/*                DEF: mtpParmeters                    */
void mtpParameters(FILE *ptr) {
char tmp[250], tmp2[250], tmp3[350];

  if (run_on_single_ctg) sprintf(tmp,"Contig %d",ctg);
  else strcpy(tmp, "All contigs");

  if (prefer_large) strcpy(tmp2,"Prefer large");
  else tmp2[0] = '\0';

  if (use_fp_pairs) {
     if (Use_sizes) strcpy(tmp3, "Use Sizes");
     else tmp3[0] = '\0';
  } else tmp3[0] = '\0';

  if (ptr == 0)
  {
     printf("Unable to open output file\n");fflush(0);return;
  }
  fprintf(ptr,"// %s  %s  %s  Mandatory: ",tmp, tmp2, tmp3);
  if ((mandatory_seqstats & TILE_MASK)) fprintf(ptr,"Tile ");
  if ((mandatory_seqstats & SENT_MASK)) fprintf(ptr,"Sent ");
  if ((mandatory_seqstats & READY_MASK)) fprintf(ptr,"Ready ");
  if ((mandatory_seqstats & SHOTGUN_MASK)) fprintf(ptr,"Shotgun ");
  if ((mandatory_seqstats & FINISHED_MASK)) fprintf(ptr,"Finished ");
  if ((mandatory_seqstats & SD_MASK)) fprintf(ptr,"SD ");
  fprintf(ptr,"\n");
}

static void hitCR(){
  int tempctg;
  int tempScore;
  int tempId;
  int clear_old=FALSE;

  if(graphActivate(gMTP)){
    sscanf(contigText,"%d", &tempctg);
    sscanf(minOlapText,"%d", &minOlap);
    sscanf(maxOlapText,"%d", &maxOlap);
    sscanf(minSharedText,"%d", &minShared);
    sscanf(maxSharedText,"%d", &maxShared);
    sscanf(uniqueSharedText,"%d", &uniqueShared);
    sscanf(fpText,"%d", &max_span_mis);
    sscanf(fp2Text,"%d", &max_flank_mis);
    sscanf(minScoreText,"%d", &tempScore);
    sscanf(minIdText,"%d", &tempId);
    sscanf(selCtgText,"%d", &selected_ctg);
    sscanf(weightText, "%d", &spanmis_weight);
    sscanf(endText,"%d",&Pz.fromendInt);

    if(tempScore != minScore){
      minScore=tempScore;
      clear_old=TRUE;
    }
    if(tempId != minId){
      minId=tempId;
      clear_old=TRUE;
    }

    if(tempctg>max_contig){
      printf("Not that many contigs!\n");
      ZselectMTP();
    }
    else if(contigs[tempctg].count==0){
      printf("Ctg%d does not exist!\n",tempctg);
      ZselectMTP();
    }
    else{
      ctg=tempctg;
      messageText[0]='\0';
      messageText2[0]='\0';
    }
    if(clear_old){
      if(have_pairs) free_pairs_mem();
      if(have_picks) free_picks_mem();
      have_pairs=FALSE;
      have_picks=FALSE;
      graphBoxDraw(pairsBox, BLACK, WHITE);
      graphBoxDraw(picksBox, BLACK, WHITE);
    }
    if(graphActivate(g9a)) 
      EvalCtgDisplay();
   
    if(graphActivate(g92)) 
      ClamCtgDisplay2();
  
    if(graphActivate(gEvaluateClone)) 
      ZevaluateClone();
    
    ZselectMTP();
  }
  else if(graphActivate(gStep)){
    hitCR2();
  } 
}

static void hitCR2(){
  int tempctg;

  if(graphActivate(gStep)){
    sscanf(contigText,"%d", &tempctg);
    if(tempctg>max_contig){
      printf("Not that many contigs!\n");
      ZstepWindow();
    }
    else if(contigs[tempctg].count==0){
      printf("Ctg%d does not exist!\n",tempctg);
      ZstepWindow();
    }
    else{
      ctg=tempctg;
      messageText[0]='\0';
      messageText2[0]='\0';
    }
  }
}

static void hitCR3(){
  if(graphActivate(gAdvancedBSS)){
    sscanf(maxSeqOlapText,"%d", &max_seq_olap);
    sscanf(multCtgRatioText,"%d", &mult_ctg_ratio);
  }
}

static void pickg(int box,double x,double y){
  /* martin 14 feb 05, eliminated re-creation of graphTextEntry boxes */
  if(box == fpArc){ use_fp_pairs = !use_fp_pairs; ZselectMTP();}
  else if(box == size1Arc){ Use_sizes = !Use_sizes; ZselectMTP();}
  else if(box == size2Arc){ Use_sizes = !Use_sizes; ZselectMTP();}
  else if(box == bssArc){ use_bss_pairs = !use_bss_pairs; ZselectMTP();}
  else if(box == showFpArc){show_fp = !show_fp; ZselectMTP();}
  else if(box == allCtgArc){run_on_single_ctg = FALSE; ZselectMTP();}
  else if(box == singleCtgArc){run_on_single_ctg = TRUE; ZselectMTP();}
  else if(box == largeClnArc){prefer_large = !prefer_large; ZselectMTP();}
}

static void pickg2(int box,double x,double y){
  /* martin 14 feb 05, eliminated re-creation of graphTextEntry boxes */
  if(box == onlySingleArc){ only_single_bes = !only_single_bes; ZadvancedBSS();}
  else if(box == onlyPosArc){only_pos_olap = !only_pos_olap; ZadvancedBSS();}
}

guint
num_shared_bands(int index1, int index2)
{
    guint i, j;
    guint result = 0;
    gint diff, tol;

    loadCzfast(&C1z, index1);
    loadCzfast(&C2z, index2);

    /* Find matches between clones */
    for (i = 0, j = 0; i < C1z.nbands; i++) {
        tol = 0;
        diff = 0;
        while (!tol && diff >= 0 && j < C2z.nbands) {
            diff = C1z.coords[i] - C2z.coords[j];
            tol = Ztol(C1z.coords[i], diff);
            ++j;
        }
        if (tol)
            ++result;
        else if (diff < 0)
            --j;
    }

    return result;
}

void
find_pairs(gboolean use_fp, gboolean use_bss,
           gint min_olap, gint max_olap, guint min_shared, guint min_unique)
{
    use_fp_pairs = use_fp;
    use_bss_pairs = use_bss;
    minOlap = min_olap;
    maxOlap = max_olap;
    minShared = min_shared;
    uniqueShared = min_unique;
    find_pairs_callback();
}

void
find_mtp(gint shared_w, gint unacc_w, gint spanmis_w)
{
    shared_weight =  shared_w;
    unacc_weight = unacc_w;
    spanmis_weight = spanmis_w;
    pick_mtp_clones();
}

void
output_mtp(void)
{
    write_picked();
}



void
quitMandatoryClones(void)
{
  if (graphActivate(gMandatoryClones)) {
      graphDestroy();
      ZselectMTP();
  }
}
/*********************************************************
                  MAIN: ZmandatoryClones
 The graphics for the pairs 'Mandatory clones' window.
*********************************************************/
void
ZmandatoryClones(void)
{
    float row;
    static MENUOPT amenu[] = { {quitMandatoryClones, "Close"},
                               {graphPrint,"Print Screen"},
                               {0, 0} };

    if (graphActivate(gMandatoryClones)) {
        graphPop();
    }
    else {
        gMandatoryClones =
            graphCreate(TEXT_FIT, "Mandatory clones", 0.2, 0.2, 0.330, 0.280);
        graphRegister(PICK, pickg3);
    }

    graphClear();
    graphMenu(amenu);

    row = 1.0;
    graphText("Mandatory clone sequence status", 3, row);

    row += 2.0;
    graphText("Tile", 3, row);
    tileArc = graphBoxStart();
    graphArc(1.0, row + 0.5, 0.7, 0, 360);
    if (mandatory_seqstats & TILE_MASK)
        graphFillArc(1.0, row + 0.5, 0.4, 0, 360);
    graphBoxEnd();
    graphBoxDraw(tileArc, BLACK, TRANSPARENT);

    row += 2.0;
    graphText("Sent", 3, row);
    sentArc = graphBoxStart();
    graphArc(1.0, row + 0.5, 0.7, 0, 360);
    if (mandatory_seqstats & SENT_MASK)
        graphFillArc(1.0, row + 0.5, 0.4, 0, 360);
    graphBoxEnd();
    graphBoxDraw(sentArc, BLACK, TRANSPARENT);

    row += 2.0;
    graphText("Ready", 3, row);
    readyArc = graphBoxStart();
    graphArc(1.0, row + 0.5, 0.7, 0, 360);
    if (mandatory_seqstats & READY_MASK)
        graphFillArc(1.0, row + 0.5, 0.4, 0, 360);
    graphBoxEnd();
    graphBoxDraw(readyArc, BLACK, TRANSPARENT);

    row += 2.0;
    graphText("Shotgun", 3, row);
    shotgunArc = graphBoxStart();
    graphArc(1.0, row + 0.5, 0.7, 0, 360);
    if (mandatory_seqstats & SHOTGUN_MASK)
        graphFillArc(1.0, row + 0.5, 0.4, 0, 360);
    graphBoxEnd();
    graphBoxDraw(shotgunArc, BLACK, TRANSPARENT);

    row += 2.0;
    graphText("Finished", 3, row);
    finishedArc = graphBoxStart();
    graphArc(1.0, row + 0.5, 0.7, 0, 360);
    if (mandatory_seqstats & FINISHED_MASK)
        graphFillArc(1.0, row + 0.5, 0.4, 0, 360);
    graphBoxEnd();
    graphBoxDraw(finishedArc, BLACK, TRANSPARENT);

    row += 2.0;
    graphText("SD", 3, row);
    sdArc = graphBoxStart();
    graphArc(1.0, row + 0.5, 0.7, 0, 360);
    if (mandatory_seqstats & SD_MASK)
        graphFillArc(1.0, row + 0.5, 0.4, 0, 360);
    graphBoxEnd();
    graphBoxDraw(sdArc, BLACK, TRANSPARENT);

    row += 2.0;
    graphButton("Close", quitMandatoryClones, 8, row);
    graphButton("Help", show_mandatory_clones_help, 1, row);

    graphRedraw();
}

/*********************************************************
                  MAIN: ZselectMTP
 The graphics for the 'Select MTP' window.
*********************************************************/
void ZselectMTP(){
  int i;
  float row;
  float scale = .9;
  static MENUOPT amenu[] = { {quitMTP, "Close"},
                             { graphPrint,"Print Screen"},
                             { 0, 0 } };

  quitStep();

  if(graphActivate(gMTP)){
    graphPop();
  }
  else{
    gMTP = graphCreate (TEXT_FIT,"Select MTP",.2,.2,.457,.970*scale);
    graphRegister (PICK, pickg) ;
  }

  if (currentctg > 0) ctg = currentctg;
  else if(ctg==-1){
    for(i=1;i<=max_contig;i++){
      if(contigs[i].count>0){
        ctg = i;
        break;
      }
    }
  }
  sprintf(contigText,"%d",ctg);
  sprintf(minOlapText,"%d",minOlap);
  sprintf(maxOlapText,"%d",maxOlap);
  sprintf(minSharedText,"%d",minShared);
  sprintf(maxSharedText,"%d",maxShared);
  sprintf(uniqueSharedText,"%d",uniqueShared);
  sprintf(fpText,"%d",max_span_mis);
  sprintf(fp2Text,"%d",max_flank_mis);
  sprintf(minScoreText,"%d",minScore);
  sprintf(minIdText,"%d",minId);
  sprintf(selCtgText,"%d",selected_ctg);
  sprintf(weightText, "%d", spanmis_weight);
  sprintf(endText,"%d",Pz.fromendInt);
 
  mand_num = 0;
  if (mandatory_seqstats & TILE_MASK) mand_num++;
  if (mandatory_seqstats & SENT_MASK) mand_num++;
  if (mandatory_seqstats & READY_MASK) mand_num++;
  if (mandatory_seqstats & SHOTGUN_MASK) mand_num++;
  if (mandatory_seqstats & FINISHED_MASK) mand_num++;
  if (mandatory_seqstats & SD_MASK) mand_num++;
  sprintf(mandnumText, "%d options selected", mand_num);

  graphClear();
  graphMenu(amenu);

  row = 1.0;

  graphText("STEP 1: ", 1, row);
  pairsBox = graphButton("Find overlapping pairs",find_pairs_callback,9,row);
  if (have_pairs) graphBoxDraw(pairsBox, BLACK, LIGHTGRAY);
  else graphBoxDraw(pairsBox, BLACK, WHITE);

  row += 2.0*scale;
  graphText("Min FPC Overlap:",1,row);
  minOlapBox = graphTextEntry(minOlapText, 4, 18, row,hitCR);

  graphText("Max FPC Overlap:",24,row);
  maxOlapBox = graphTextEntry(maxOlapText, 4, 41, row,hitCR);

  row += 2.0*scale;
  graphText("FromEnd:",1,row);
  endBox = graphTextEntry(endText, 4, 10, row,hitCR);

  row += 2.5*scale;
  graphText("Use Fingerprints:",4,row);
  fpArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (use_fp_pairs) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(fpArc, BLACK, TRANSPARENT);

  row += 2.0*scale;
  graphText("Min Shared Bands:",2,row);
  minSharedBox = graphTextEntry(minSharedText, 4, 20, row,hitCR);

//  graphText("Weight:", 25, row);
//  weightBox = graphTextEntry(weightText, 4, 33, row, hitCR);

  if (Pz.fp_class!=HICF) {
     graphText("Use Sizes",41,row);
     size1Arc = graphBoxStart();
     graphArc(40.0, row+0.5, 0.7, 0, 360);
     if (Use_sizes) graphFillArc(40.0, row+0.5, 0.4, 0, 360);
     graphBoxEnd();
     graphBoxDraw(size1Arc, BLACK, TRANSPARENT);
  }
  row += 2.5*scale;

  graphText("Use BSS results",4,row);
  bssArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (use_bss_pairs) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(bssArc, BLACK, TRANSPARENT);

  row += 2.0*scale;
  graphText("BSS File:",2,row);
  bssFileBox = graphTextScrollEntry(bssFileText, MAXPATHLEN, 28, 12, row,hitCR);
  graphButton("Load",browse_bss_file,41,row);

  row += 2.0*scale;
  graphText("Filter BLAST Score:",2,row);
  minScoreBox = graphTextEntry(minScoreText, 4, 22, row,hitCR);

  graphText("Identity:",28,row);
  minIdBox = graphTextEntry(minIdText, 4, 38, row,hitCR);

  row += 2.0*scale;
  graphButton("Advanced settings", ZadvancedBSS, 2, row);

  row += 2.5*scale;
  graphText("Or use existing Pairs File:", 1, row);
  row += 2.0*scale;
  pairsFileBox = graphTextScrollEntry(pairsFileText, MAXPATHLEN, 38, 2, row,
                 get_pairs_file_name_from_text_box);
  graphButton("Load",get_pairs_file_name_by_query,41,row);

  row += 2.5*scale;
  graphLine(1, row, 50, row);

  row += 1.0*scale;
  graphText("STEP 2: ", 1, row);
  picksBox = graphButton("Pick MTP clones",pick_mtp_clones,9,row);
  if (have_picks) graphBoxDraw(picksBox, BLACK, LIGHTGRAY);
  else graphBoxDraw(picksBox, BLACK, WHITE);

  row += 2.0*scale;
  graphText("All contigs",4,row);
  allCtgArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (!run_on_single_ctg) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(allCtgArc, BLACK, TRANSPARENT);

  graphText("Contig",20,row);
  singleCtgArc = graphBoxStart();
  graphArc(18.0, row+0.5, 0.7, 0, 360);
  if (run_on_single_ctg) graphFillArc(18.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(singleCtgArc, BLACK, TRANSPARENT);
  selCtgBox = graphTextEntry(selCtgText, 6, 27, row, (void *) hitCR);

  row += 2.0*scale;
  graphText("Give preference to large clones",4,row);
  largeClnArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (prefer_large) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(largeClnArc, BLACK, TRANSPARENT);

  if (Pz.fp_class!=HICF) {
     graphText("Use Sizes",39,row);
     size2Arc = graphBoxStart();
     graphArc(38.0, row+0.5, 0.7, 0, 360);
     if (Use_sizes) graphFillArc(38.0, row+0.5, 0.4, 0, 360);
     graphBoxEnd();
     graphBoxDraw(size2Arc, BLACK, TRANSPARENT);
  }

  row += 2.0*scale;
  graphButton("Mandatory clones", ZmandatoryClones, 1, row);
  graphText(mandnumText, 20, row); 

  row += 2.5*scale;
  graphLine(1, row, 50, row);

  row += 1.0*scale;
  graphText("STEP 3: View results (if desired)",1,row);
  row += 2.0*scale;
  graphButton("Mini Window",ZstepWindow,1,row);
  graphText("Contig",17,row);
  contigBox = graphTextEntry(contigText, 6, 24, row, (void *) hitCR);

  row += 2.0*scale;
  graphText("Step through pairs:",1,row);
  graphButton("Next",next_pairs,23,row);
  graphButton("Previous",prev_pairs,29,row);
  pickStartBox = graphButton("Pick start",pick_start,39,row);
  if (pick_pair_start) graphBoxDraw(pickStartBox, BLACK, RED);
  else graphBoxDraw(pickStartBox, BLACK, WHITE);

  row += 2.0*scale;
  graphText("Step through MTP:",1,row);
  graphButton("Next",next_pick,23,row);
  graphButton("Previous",prev_pick,29,row);
  graphButton("All",all_pick,39,row);

  row += 2.0*scale;
  graphText("Show fingerprints (Fp only)",4,row);
  showFpArc = graphBoxStart();
  graphArc(2.0, row+0.5, 0.7, 0, 360);
  if (show_fp) graphFillArc(2.0, row+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(showFpArc, BLACK, TRANSPARENT);

  row += 2.0*scale;
  messageBox = graphBoxStart();
  graphTextPtr(messageText,1.0,row,49);
  graphBoxEnd();
  graphBoxDraw(messageBox,BLACK,CYAN);

  row += 2.0*scale;
  messageBox2 = graphBoxStart();
  graphTextPtr(messageText2,1.0,row,49);
  graphBoxEnd();
  graphBoxDraw(messageBox2,BLACK,CYAN);

  row += 2.0*scale;
  graphButton("Set MTP clone status to TILE for contig",set_tile_ctg_only,1,row);

  row += 2.5*scale;
  graphLine(1, row, 50, row);

  row += 1.0*scale;
  graphText("STEP 4: Save results", 1,row);
  row += 2.0*scale;
  graphButton("Set MTP clone status to TILE",set_tile_all,1,row);
  graphButton("Clear TILE",clear_tile,32,row);
  row += 2.0*scale;
  graphText("File of Pairs:",1,row);
  graphButton("Save",save_pairs_file,21,row);
  row += 2.0*scale;
  graphText("File of MTP clones:",1,row);
  graphButton("Save",write_picked,21,row);

  row += 2.5*scale;
  graphLine(1, row, 50, row);

  row += 1.0*scale;
  graphButton("Eval Clone Seq->BES Results", ZevaluateClone, 1, row);

  row += 2.5*scale;
  graphButton("Close",quitMTP,1,row);
  graphButton("Help",show_mtp_help,8,row);

  graphRedraw();
}


